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?
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.