我有一个很小的 TCP 应用程序,其中许多客户端连接到服务器,向其发送数据(通过 write() - 它们也发送消息大小),然后退出。我让客户端在发送完成后将 \0\0 发送到服务器 - 我这样做是为了如果服务器从 read() 得到一个零,那么它就知道客户端出了问题(比如 SIGKILL)。我的问题是 - 是否有任何编程方式(某些系统调用)来通知服务器我已完成发送 - 而不是服务器始终检查 \0\0 ?服务器在客户端/侦听套接字上使用 poll() 来检测是否有要读取的内容/新的连接请求,顺便说一句。
我应该发出信号吗?但我如何知道哪个描述符停止轮询呢?
我读过这篇文章,但其中的答案或多或少是我现在使用的
\0\0如果您的协议比单个请求/响应模型稍微复杂一点,那么在应用程序级别执行此操作(例如,使用您正在执行的操作)是正确的方法。
例如,HTTP 1.0 在单个请求/响应后立即关闭连接:客户端发送其请求命令,服务器回复其响应并关闭连接。
在具有更复杂交换的协议中,有特定的命令来指示消息的结束。例如,SMTP 和 POP3 是行分隔的。通过 SMTP 发送电子邮件内容时,您可以使用.单行指示消息的结尾(.在实际消息中转义为..)。您还会收到诸如QUIT指示您已完成之类的命令。
在HTTP 1.1中,请求标头集以空行终止(例如GET / HTTP/1.1+一行上的每个标头+一个空行),因此服务器知道请求的结尾在哪里。然后,HTTP 1.1 中的响应使用Content-Length标头(在响应正文即将结束时发出信号)或使用分块传输编码,该编码本质上会插入许多分隔符来指示是否有更多数据即将到来(通常,它在以下情况下使用):服务器事先不知道数据大小)。(具有正文的请求也使用相同的标头来指示请求何时结束。)
否则,服务器很难知道它何时完成读取,因为通常不可能检测套接字是否已断开连接(或者更确切地说,即使客户端没有发送任何数据,它是否仍然连接)。通过在应用程序级别发送一些分隔符或长度指示符,您可以避免此类问题(或者可以检测何时出现问题/超时)。