[Solved] Async Read/Write using TcpStream


#1

Hi everyone, I am having difficulties figuring out to how to read from a TcpStream in a separate thread and write to it from the main thread.
Here is an example to better visualize the problem:

use std::io::prelude::*;
use std::io::{stdin, BufReader, BufWriter, Write};
use std::net::TcpStream;
use std::thread;

fn main() {
    let mut stream = TcpStream::connect("127.0.0.1:3030").unwrap();
    let mut reader = BufReader::new(&stream);
    let mut writer = BufWriter::new(&stream);
    let mut line = String::new();

    thread::spawn(move || loop {
        let res = reader.read_line(&mut line);
        match res {
            Ok(len) => {
                if len == 0 {
                    break;
                }
                println!("Received: {}", line);
            }
            Err(_) => {
                break;
            }
        }
    });

    let mut input = String::new();
    loop {
        let res = stdin().read_line(&mut input);
        match res {
            Ok(_) => {
                writer.write(input.as_bytes());
            }
            Err(_) => {
                break;
            }
        }
    }
}

This will result in an error saying:

stream does not live long enough                                                                                      
 --> src/main.rs:8:37                                                                                                                
  |                                                                                                                                  
8  |     let mut reader = BufReader::new(&stream);                                                                                    
  |                      ---------------^^^^^^^-                                                                                     
  |                      |              |                                                                                            
  |                      |              borrowed value does not live long enough                                                     
  |                      argument requires that stream is borrowed for 'static                                                   
…                                                                                                                                   
39 | }                                                                                                                                
  | - stream dropped here while still borrowed

This makes sense, since the stream is dropped at the end of the main function while it’s still borrowed by reader which probably outlives stream since it’s moved to the new thread. (I am not sure if I understood the error message, so correct me if I’m wrong)
So I tried to modify the code to make stream have a static lifetime:

let stream: &'static TcpStream = &TcpStream::connect("127.0.0.1:3030").unwrap();
let mut reader = BufReader::new(stream);
let mut writer = BufWriter::new(stream);

This results in another error saying that &TcpStream::connect("127.0.0.1:3030").unwrap();creates a temporary which is freed while still in use”, which again makes sense, but here is where I couldn’t find a solution, and started to think that I am doing this totally wrong.
I would basically like to know how to share a resource between multiple threads in rust and how this particular example could be solved. Thanks !


#2

Take a look at TcpStream::try_clone. Using it, the code could look like:

fn main() {
    let rstream = TcpStream::connect("127.0.0.1:3030").unwrap();
    let wstream = rstream.try_clone().unwrap();
    
    let mut reader = BufReader::new(rstream);
    let mut writer = BufWriter::new(wstream);
...
}

#3

Thank you, it works. :smiley: