quinn-rs / quinn

Async-friendly QUIC implementation in Rust
Apache License 2.0
3.76k stars 380 forks source link

Must finish() be called after sending data? #1255

Closed go-jar closed 2 years ago

go-jar commented 2 years ago

After sending data by SendStream, I must call finish() to make peer receive data.

send.write_all(request.as_bytes())
    .await
    .map_err(|e| anyhow!("failed to send request: {}", e))?;
send.finish()
    .await
    .map_err(|e| anyhow!("failed to shutdown stream: {}", e))?;

But I want to use the same stream to send data and peer can receive data every time. I don't know how to make it, because SendStream has no method flush(). Client:

send.write_all(b"hello")
    .await
    .map_err(|e| anyhow!("failed to send request: {}", e))?;
send.flush()

send.write_all(b"world")
    .await
    .map_err(|e| anyhow!("failed to send request: {}", e))?;
send.flush()

send.finish()
    .await
    .map_err(|e| anyhow!("failed to shutdown stream: {}", e))?;

Server:

let resp = recv
        .read_to_end(usize::max_value())
        .await
        .map_err(|e| anyhow!("failed to read response: {}", e))?;
println!("recv: {:?}", resp);

let resp1 = recv
        .read_to_end(usize::max_value())
        .await
        .map_err(|e| anyhow!("failed to read response: {}", e))?;
println!("recv: {:?}", resp1);
Ralith commented 2 years ago

Data on streams is sent immediately; there is no need to flush. Finish is only for indicating when you are permanently done sending data on that stream.

go-jar commented 2 years ago

Data on streams is sent immediately; there is no need to flush. Finish is only for indicating when you are permanently done sending data on that stream.

Thanks! But server won't receive any data until client call finish(). And once the finish() is called, the send stream is terminated. So client must call conn.open_uni() or conn.open_bi() to send data again. How can client send data on the same stream and server can receive data from client every time?

djc commented 2 years ago

Well, you're using read_to_end() on the server, so of course the server-side reads won't give you anything until the client calls finish().

go-jar commented 2 years ago

Well, you're using read_to_end() on the server, so of course the server-side reads won't give you anything until the client calls finish().

Thanks! Do you mean that after client using send_to_end() to send data without calling finish(), then the server can use read() to get data immediately? I will try it.

Ralith commented 2 years ago

read will yield any available data, yeah. Note that just like TCP, write boundaries are not preserved within streams, so if you want to send discrete messages on a single stream you'll need some form of framing (e.g. tokio's LengthDelimited codec)

go-jar commented 2 years ago

read will yield any available data, yeah. Note that just like TCP, write boundaries are not preserved within streams, so if you want to send discrete messages on a single stream you'll need some form of framing (e.g. tokio's LengthDelimited codec)

Thanks!