Why is my Server appears to only able works whenever my `BufWriter` and `BufReader` are in a separate function?

huangapple go评论74阅读模式
英文:

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, &quot;GET|1|ALL&quot;).unwrap();
&lt;strong&gt;my_buf_writer.flush().unwrap();&lt;/strong&gt;

let mut my_buf_reader = BufReader::new(&amp;stream);

let mut buffer = String::new();

println!(&quot;Reading line&quot;);
my_buf_reader.read_line(&amp;mut buffer).unwrap(); // Doesn&#39;t stop

println!(&quot;{}&quot;, 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.

huangapple
  • 本文由 发表于 2023年5月21日 22:03:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76300288.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定