I am currently working on a chat server using tokio with its utilities. Assume the server receives a connection:
let listener = TcpListener::bind("0.0.0.0:1234").await?;
let (stream, _) = listener.accept().await?;
By doing below, I am able to read or write lines:
let mut lines = Framed::new(stream, LinesCodec::new());
lines.send("write a line to client").await?;
let string_from_client = lines.next().unwrap();
However, if I want to send files, images, etc. I may need to use other codec(BytesCodec
), while TcpStream is consumed by the constructor of Framed.
How am I able to do that? If there is a solution, how can I drop the TcpStream and disable all Framed(s) after shutdown gracefully?
You can use Framed::into_inner
to get the underlying stream back:
let mut lines = Framed::new(stream, LinesCodec::new());
lines.send("write a line to client").await?;
let string_from_client = lines.next().await;
let stream = lines.into_inner();
Though, be careful, as this drops the internal state of the LinesCodec
and, more importantly, this drops the state of the Framed
that contains the read- and write-buffers. So if you for example received foo\nbar
, read foo
, and now call into_inner
, you're discarding bar
(it's in the read-buffer of the Framed
).
Your use-case sounds like you might want to implement your own Decoder
and Encoder
. The Decoder
could for example decode into a enum { Text(String), Bytes(Bytes) }
.
how can I drop the TcpStream and disable all Framed(s) after shutdown gracefully?
When dropping the Framed
, you're also dropping the TcpStream
(it's contained inside the Framed
).