currently I'm using bincode to serialize struct into Vec<u8>
and first send its length as u64 and then data over Async TcpStream
from tokio.
Server:-
use std::{convert::TryInto, net::SocketAddr};
use tokio::{io::AsyncWriteExt, net::{TcpListener, TcpStream}};
use serde::{Serialize,Deserialize};
#[derive(Serialize,Deserialize,Debug, Default)]
struct Msg {
f1: String,
f2: bool,
f3: f64
}
#[tokio::main]
async fn main() {
let listener = TcpListener::bind("127.0.0.1:61717").await.unwrap();
loop {
match listener.accept().await {
Ok((socket, addr)) => {
tokio::spawn( async move { process_socket(socket, addr).await } );
},
Err(e) => {
eprintln!("couldn't get client: {:?}", e);
continue
}
}
}
}
async fn process_socket(mut socket : TcpStream, addr : SocketAddr) {
println!("New connection from {}",addr);
let m2 = Msg {
f1 : "rust is love".into(),
f2 : true,
f3 : 75240.5534
};
let data = bincode::serialize(&m2).unwrap();
let len :u64 = data.len().try_into().unwrap();
socket.write_u64(len).await.unwrap();
socket.write(&data).await.unwrap();
}
and then on client I get data like this:-
let len = socket.read_u64().await.unwrap();
let mut data : Vec<u8> = Vec::with_capacity(len.try_into().unwrap());
socket.read_to_end(&mut data).await.unwrap();
let msg : Msg = bincode::deserialize(&data).unwrap();
But I think this is not the best approach as when I serialize Msg
on server, I have 2 copies of same data one in form of Msg
and another in form of Vec<u8>
. I'm planning to send large size of data like png files and this would not be ideal use of RAM as far as I know.
There is method in bincode to serialize directly into writer but idk how use it. is there some way to directly serialize into Async TcpStream
? or any better aproach ?