Unix 套接字的双向通信

问题描述

我正在尝试创建一个设置 Unix 套接字并侦听发送/接收数据的客户端的服务器。我做了一个 small repository 来重现这个问题。

服务器运行并且它可以从连接的客户端接收数据,但是我无法在服务器上没有错误的情况下从客户端读取服务器响应。

我已注释掉 clientserver 上的违规代码。取消注释以重现问题。

当响应客户端的代码被取消注释时,我在服务器上收到此错误

线程 '' 在 Result::unwrap() 值上的 'call Err 处恐慌:Os { 代码:11,种类:WillBlock,消息:“资源暂时不可用”}',src/main.rs: 77:42

MRE Link

解决方法

您的代码调用 set_read_timeout 来设置套接字超时。它的文档指出,在 Unix 上,它会在超时的情况下导致 WouldBlock 错误,而这正是您遇到的情况。

至于您的客户端为什么超时,可能的原因是服务器调用了 stream.read_to_string(&mut response),它读取流直到文件结束。另一方面,您的客户端调用 write_all() 后跟 flush(),并且(在取消注释违规代码后)尝试读取响应。但是尝试读取响应意味着流没有关闭,因此服务器将等待 EOF,您将陷入僵局。请注意,这些都不是 Rust 特有的;你会在 C++ 或 Python 中遇到完全相同的问题。

要解决此问题,您需要在通信中使用协议。一个非常简单的协议可能包括首先发送消息大小(以固定格式,长度可能为 4 个字节),然后才是实际的消息。从流中读取的代码将执行相同的操作:首先读取消息大小,然后读取消息本身。比发明自己的协议更好的是使用现有的协议,例如使用 serde 交换消息。