-1

I'm trying to create a server that sets up a Unix socket and listens for clients which send/receive data. I've made a small repository to recreate the problem.

The server runs and it can receive data from the clients that connect, but I can't get the server response to be read from the client without an error on the server.

I have commented out the offending code on the client and server. Uncomment both to recreate the problem.

When the code to respond to the client is uncommented, I get this error on the server:

thread '' panicked at 'called Result::unwrap() on an Err value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', src/main.rs:77:42

MRE Link

mattlennon3
  • 1
  • 1
  • 3
  • It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Mar 08 '21 at 17:22
  • [To make Stack Overflow a useful resource for future visitors beyond the context of your repository](https://meta.stackoverflow.com/q/380194/155423), please [edit] your question to add a [MRE] in the question itself, in addition to the link to your repository. – Shepmaster Mar 08 '21 at 17:22

1 Answers1

-1

Your code calls set_read_timeout to set the timeout on the socket. Its documentation states that on Unix it results in a WouldBlock error in case of timeout, which is precisely what happens to you.

As to why your client times out, the likely reason is that the server calls stream.read_to_string(&mut response), which reads the stream until end-of-file. On the other hand, your client calls write_all() followed by flush(), and (after uncommenting the offending code) attempts to read the response. But the attempt to read the response means that the stream is not closed, so the server will wait for EOF, and you have a deadlock on your hands. Note that none of this is specific to Rust; you would have the exact same issue in C++ or Python.

To fix the issue, you need to use a protocol in your communication. A very simple protocol could consist of first sending the message size (in a fixed format, perhaps 4 bytes in length) and only then the actual message. The code that reads from the stream would do the same: first read the message size and then the message itself. Even better than inventing your own protocol would be to use an existing one, e.g. to exchange messages using serde.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • Since you've looked at the code, do you think this is a duplicate of [Simple Rust TCP server and client do not receive messages and never terminates](https://stackoverflow.com/q/44015638/155423)? Or maybe [Reading from a TcpStream with Read::read_to_string hangs until the connection is closed by the remote end](https://stackoverflow.com/q/30552187/155423)? – Shepmaster Mar 08 '21 at 17:43
  • @Shepmaster It looks like the same issue in essence, just differing in details - e.g. the code in the older question failed to flush the `BufWriter`. – user4815162342 Mar 08 '21 at 17:48
  • I was going to move on to `serde` when I got around to sending actual data structures. I figured sending a string would be simpler to start with :/. If I remove the `set_read_timeout`, I get a `broken pipe` error. Is this because I call `.flush()` on the client and the server does not find the EOF? It's just strange because it does actually print the string received. – mattlennon3 Mar 08 '21 at 18:14
  • @mattlennon3 A broken pipe typically means that writing has failed because the other side has disconnected. It's hard to tell why that happens to you without seeing the exact source you are running. And even that is not effort well spent because the current approach is fundamentally flawed, as argued in my answer and in the answers to questions linked by Shepmaster in the comments. I suggest that instead of trying to salvage a flawed design, you study the problem and structure your code around a better one. – user4815162342 Mar 08 '21 at 18:32
  • @user4815162342 Back to the drawing board! Thanks very much for your time. Should I delete this question or just mark it as answered? – mattlennon3 Mar 08 '21 at 18:36
  • @mattlennon3 That's up to you - if you think that it doesn't improve the site (also in light of the previous questions highlighted by Shepmaster), feel free to delete it. – user4815162342 Mar 08 '21 at 18:51