英文:
Why is my Server appears to only able works whenever my `BufWriter` and `BufReader` are in a separate function?
问题
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?
英文:
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?
答案1
得分: 1
问题在于数据不会写入TcpStream
直到你调用flush
方法,BufWriter
在被释放时会自动执行。除非执行flush
,否则服务器将一直等待客户端开始通信,而客户端将一直等待服务器响应未发送的消息,换句话说,你陷入了死锁。
在你的帖子和评论中已经提到的两个解决方案之外,确保数据已经通过flush
发送也是有效的:
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);
}
提示:在作为“服务器”的控制台上运行简单的nc -l 9073
可以帮助调试此类问题,这样你就能在服务器控制台上看到“Reading line”消息,而在发送任何数据之前。
英文:
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:
<pre><code>
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();
<strong>my_buf_writer.flush().unwrap();</strong>
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);
}
</code></pre>
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论