Why does iterating over a BufReader.lines() in a Server and Client doesn't end until I explicitly break the loop in the server

Advertisements

I’m currently learning about the TcpStream and TcpListener so I’m trying to explore a little bit about it.

I have encounter this problem, specificially, I have this code in server.rs

    let my_listener = TcpListener::bind("127.0.0.1:8000").unwrap();

    for connection_stream in my_listener.incoming(){
        println!("Got a connection");
        let mut my_connection = connection_stream.unwrap();


        let some_buffer = BufReader::new(&my_connection);
        let buffer_data = some_buffer.lines();

        for data in buffer_data{
            println!("Data: {}", data.unwrap());
            
            // If I put `break` here, everything would work.
        }

        my_connection.write(b"Hello World").unwrap();

        println!("A Successful Interaction");
    }

and this in client.rs

    loop{
        let mut my_stream = TcpStream::connect("127.0.0.1:8000").unwrap();
        
        let mut my_input = String::new();
        std::io::stdin().read_line(&mut my_input).unwrap();
        
        my_stream.write(my_input.as_bytes()).unwrap();
        
        let buf_reader = BufReader::new(&my_stream);

        for values in buf_reader.lines(){
            println!("{}", values.unwrap());

            // but if I put `break` here, nothing really happens.
        }
        
        println!("This will not print until a connect has been establish");
    
    }

If I entered any value in any instance of any client, say watermelon, this would be the result:

Client

[1] watermelon // my input
[3] // can't input anymore

Server

[0] Got a Connection
[2] Data: watermelon

After a connection has been establish, [0] would print in the server, then after I input [1], the server would print out [2] but then i can’t input anymore [3].

If I add break in the server.rs .lines() loop , it would now work. However, If I add break in the client .lines() loop, it still wouldn’t work.

Why is this happening? and what are the different ways I can fix it?

>Solution :

Iterating over lines() will not stop when there is no more data in the stream; it will block until more data is sent, and only stop when the stream is closed. So the client is waiting for the server to send data and the server is waiting for the client to send data, hence a deadlock.

You can spawn a thread that will read data from stdin and send it to the stream, and another thread will print the data received from the stream.

Leave a ReplyCancel reply