I have a client (a.rs
) and a server (b.rs
):
// a.rs
use std::{
io::{Read, Write},
net::TcpListener,
};
fn main() {
let listener = TcpListener::bind("0.0.0.0:6400").unwrap();
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let mut buf = String::new();
println!("Waiting for query...");
stream.read_to_string(&mut buf).unwrap();
println!("> Received query: {}", buf);
// Compute something based on query
let query_res = String::from("42");
println!("Writing...");
stream.write(query_res.as_bytes()).unwrap();
println!("> Done");
}
}
// b.rs
use std::{io::{Read, Write}, net::TcpStream, thread, time::Duration};
fn main() {
let mut stream = TcpStream::connect("127.0.0.1:6400").unwrap();
println!("Sending query...");
stream
.write(String::from("What is the best number?").as_bytes())
.unwrap();
println!("> Done");
println!("Receiving...");
let mut buf = String::new();
stream.read_to_string(&mut buf).unwrap();
println!("> Received: {}", buf);
}
Terminal A:
$ cargo run --bin a
Waiting for query...
Terminal B:
$ cargo run --bin b
Sending query...
> Done
Receiving...
> Received: 42
Terminal A:
> Received query: What is the best number?
Writing...
> Done
Terminal A:
$ cargo run --bin a
Waiting for query...
Terminal B:
$ cargo run --bin b
Sending query...
> Done
Receiving...
And both terminals are blocked. Why and how to solve this?
read_to_string
reads into String until EOF which will not happen until you close the stream from the writer side.
What you can do is write the query as line using writeln!
:
println!("Sending query...");
writeln!(stream, "What is the best number?").unwrap();
println!("> Done");
and create a buffered reader to read a line:
let mut stream = stream.unwrap();
let mut reader = BufReader::new(&stream);
let mut buf = String::new();
println!("Waiting for query...");
reader.read_line(&mut buf).unwrap();
println!("> Received query: {}", buf);