使用read(2)
从套接字读取并阻止I / O时,何时知道另一方(客户端)没有更多数据要发送? (通过“不再发送数据”我的意思是,作为一个例子,客户端正在等待响应)。起初,我认为count
(read
)返回的字节少于read(fd, *buf, count)
时就达到了这一点。
但是,如果客户端发送碎片数据怎么办?在read
返回0
之前阅读将是一个解决方案,但据我所知0
仅在客户端关闭连接时返回 - 否则,read
将阻止直到连接已关闭。我想过使用非阻塞I / O和select(2)
的超时,但这对我来说似乎不是一个整洁的解决方案。
有没有已知的最佳做法?
答案 0 :(得分:1)
TCP是字节流协议,而不是消息协议。如果你想要消息,你必须自己实现它们,例如使用长度字前缀,行,XML等。您可以使用ioctl()的FIONREAD选项进行猜测,但猜测就是它的全部,因为您无法知道客户端是否在传输过程中暂停了消息,或者网络是否由于某种原因这样做了。
答案 1 :(得分:1)
协议需要让您了解客户端何时完成发送消息。
常见的方法是在每个消息之前发送每条消息的长度,或者在每条消息之后发送一个特殊的终止符(类似于C中字符串末尾的NUL字符)。
答案 2 :(得分:1)
“另一方没有更多数据要发送”的概念,没有超时或传输数据中的某些语义,这是毫无意义的。通常,客户端/服务器上的代码将能够比网络传输数据更快地处理数据。因此,当您尝试read()
时,如果接收缓冲区中没有数据,这只意味着网络尚未 传输所有内容,但您无法判断下一个是否数据包将在一毫秒,一秒或一天内到达。您可能会认为第一种情况是“需要发送更多数据”,第三种情况是“不再发送数据”,第二种情况取决于您的应用程序。
如果对方没有关闭连接,您可能不知道它何时准备发送下一个数据包。
因此,除非您具有关于客户端发送内容的特定语义和知识,否则使用select()和非阻塞I / O是您可以做的最佳选择。
在特定情况下,可能还有其他方式 - 例如,如果您知道客户端将发送XML标记,某些数据和结束标记,则每 n 秒。在这种情况下,您可以在收到最后一个数据包后开始读取 n 秒,然后继续阅读,直到收到结束标记。但正如我所说,这不是一般方法,因为它需要通道上的语义。