Tokio - how to easily implement sending to socket from a stream


#1

Hi,

I’m playing with Tokio and have this case (simplified):

tcp_listener.incoming().for_each(|socket| {
  // some code

  get_lines_stream
  .and_then(|lines_stream| {
    lines_stream.for_each(|line| {
      write_all(socket, line)
        .then(|_| Ok(()))
      }
   }
}

My problem is now error: error[E0507]: cannot move out of captured outer variable in an FnMut closure

I do understand why this error is happening, it’s because write_all need to take ownership of socket and in this code it’s not possible because closure is used multiple times.

My question would be what is the right approach in this case to working code similarly simple as above example?
I think this is quite common case so there should be some nice trick, but I can’t figure it out (I guess I can implement my own future that will takes ownership of the socket and poll stream, but that would be a lot of code).


#2

Take a look at forward:

get_lines_stream
  .and_then(|lines_stream| {
    lines_stream.forward(socket)
   }

#3

Thanks - socket is tokio::net::TcpStream, which does not implement Sink - so you think best approach is to create Sink around socket? What would be easiest way to do it?


#4

OK, got it:

let framed_socket = socket.framed(LinesCodec::new());

Thanks again for hint


#5

Yes, that’s the way to do it. Sorry, I (wrongly) assumed your real code was already working with a framed value because you mentioned sending lines (of text I presume), and figured you were using the LinesCodec but left it out of the snippet.

If you wanted to use the “raw” socket, there’re ways to do it but it wouldn’t be as elegant as using streams and sinks.

Also note that it’s often useful to split() the framed to get you a Sink and Stream for the tx and rx sides of the tcp socket, both of which will still be framed individually (so you can send/receive application messages and not raw bytes). You can then operate on them individually (ie move/consume them) but also can combine them when needed.


#6

NP,
I think in this case sink and stream was best and most elegant solution, so thanks for guiding me in this way ( I should read tutorial more carefully). I tried different solutions as my goal was to explore tokio - I created also custom Future to handle it, which finally was not very difficult, but surely it was not nice.
I.