TcpStream and BufReader Behavior

I am curious as to the behavior of a BufReader struct instance in a few cases:
(1) I need to be able to read from the stream as well as write to it. So I'm guessing that the proper thing to do here would look something like this:
let mut string = String::new();
let mut reader = BufReader::new(stream.try_clone().unwrap());
stream.read(&mut string);
stream.write(b"Something\n}).unwrap();
stream.flush().unwrap();
I assume that I am correct that you can't write to a stream that is already wrapped in a BufReader?
(2) Does a call to read_line block the thread until there is text to read from the stream?
(3) Is it generally safe to assume that, if read_line returns an Err, that the connection has been closed?

To write to the wrapped stream, you can use get_mut like this:

let mut string = String::new();
let mut reader = BufReader::new(stream.try_clone().unwrap());
stream.read_line(&mut string);
stream.get_mut().write_all(b"Something\n").unwrap();
stream.get_mut().flush().unwrap();

There is no wrapper that provides buffering in both directions, unfortunately.

Yes, read_line blocks the thread until a full line has arrived. If the connection is just closed normally, then read_line will return Ok(0). When you get an error, something worse has gone wrong, but you can assume that the connection will no longer be able to transmit data.

Thanks for the reply. The fact that read_line blocks raises a new question for me, however. I am presently working on a server to manage an online holdem game. My current design idea involved one thread per stream; that thread would handle reading and writing to the client, with the data to write received via channel from other threads. But if read_line is blocking, then calls to recv on the Receiver will not run until the server receives some input from the client. That being the case, I am wondering what the best solution is here?

You are going to need more than one thread for that, e.g. maybe a thread for reading and one for writing. Or use async/await.

So I have begun experiment with small programs using async and await (since I've not played with rust's asynchronous programming yet) and have stumbled into an issue which I find confusing. I am getting this error:
error[E0670]: async fn is not permitted in the 2015 edition -->
My source of confusion is that I am being told I am using the 2015 addition of Rust, but just this morning I made sure I was running the latest version of Rust. There is a hint in the errror that I could change to the 2018 addition in cargo.toml, but I would much rather just let the compiler know that I am using the latest addition. Why am I being told I'm using the 2015 addition, and what do I need to do to update this?

That error does not mean that you are using an old compiler.

The edition scheme exists to make the newest compiler be backwards compatible with things written before 2018 while changing some things about the language that would require breaking those old codebases. Since pre-2018 edition code did not say which edition the code was written with (there was no edition system before the 2018 edition), that is what you get if you don't specify an edition.

To fix it add an edition line to your Cargo.toml.

[package]
edition = "2018"

Creating a new project with cargo new should automatically set the field for you.

That explains it. What I was doing was small enough that I was just using one .rs file and passing that to rustc for compilation. Thanks for all the assistance.

In this case you can also use rustc --edition 2018 to enable the new syntax.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.