I have this simple code that handles the request over a stream.
fn handle_request(stream: TcpStream){
// Create a buffer reader
let mut buf_reader = BufReader::new(&stream);
// Create a buffer to store the data
let mut buffer = Vec::<u8>::new();
// Read the data into the buffer
buf_reader.read_until(b'\n', &mut buffer).unwrap(); // can be replaced by `read_line()`
// Convert the buffer to a string
let str_buffer = String::from_utf8(buffer.clone()).unwrap();
// Handle the request
respond_to_client(&str_buffer, &stream); // Assume that this writes "VALUE\n" to the stream
}
and I have this code in my test.rs
to test this functionality:
Code 00
fn main(){
let mut stream = TcpStream::connect("127.0.0.1:9073").unwrap(); // server address
let mut my_buf_writer = BufWriter::new(&stream);
my_buf_writer.write(b"GET|1|ALL\n").unwrap();
let mut my_buf_reader = BufReader::new(&stream);
let mut buffer = String::new();
println!("Reading line");
my_buf_reader.read_line(&mut buffer).unwrap(); // Doesn't stop
println!("{}", buffer);
}
However, for some reason, this don't work at all UNLESS, I separate my writer
and reader
in a separte function like this:
Code 01
fn main(){
let mut stream = TcpStream::connect("127.0.0.1:9073").unwrap(); // server address
write_in_database(&stream);
read_from_database(&stream)
}
fn write_in_database(stream: &TcpStream){
let mut my_buf_writer = BufWriter::new(stream);
my_buf_writer.write(b"GET|1|ALL\n").unwrap();
}
fn read_from_database(stream: &TcpStream){
let mut my_buf_reader = BufReader::new(stream);
let mut buffer = String::new();
println!("Reading line");
my_buf_reader.read_line(&mut buffer).unwrap(); // Now for some reason, it stops.
println!("{}", buffer);
}
I don't really get what's the difference between the two. Code 00 doesn't stop reading the stream even though the returning value has \n
UNLESS I restructure my code into Code 01 then it would work. Can someone give me an explanation?
The problem is that the data doesn't get written to the TcpStream
until you flush
it, that happens automatically when the BufWriter
is dropped. Unless you do so the the server is waiting for the client to start talking, and the client is waiting for the server to respond to the unsent message in other words you're in a deadlock.
In addition to the two solutions already in your post and the comments simply ensuring that the data has ben sent with a flush
also works:
use std::net::TcpStream;
use std::io::{BufReader, BufWriter, Write, BufRead};
fn main() {
let mut stream = TcpStream::connect("127.0.0.1:9073").unwrap();
let mut my_buf_writer = BufWriter::new(&stream);
writeln!(my_buf_writer, "GET|1|ALL").unwrap();
my_buf_writer.flush().unwrap();
let mut my_buf_reader = BufReader::new(&stream);
let mut buffer = String::new();
println!("Reading line");
my_buf_reader.read_line(&mut buffer).unwrap(); // Doesn't stop
println!("{}", buffer);
}
Tip: a plain nc -l 9073
as "server" helps debug such problems, here you see the "Reading line" message on the server console before it sent any data.