Unix 中的 TCP 套接字 - 通知服务器我已完成发送 [英] TCP socket in Unix - notify server I am done sending
问题描述
我有一个很小的 TCP 应用程序,其中许多客户端连接到服务器,向其发送数据(通过 write() - 它们也发送消息大小),然后退出.我让客户端在发送完成后将 \0\0 发送到服务器 - 我这样做是为了如果服务器从 read() 获得零,那么它就知道客户端出了问题(比如 SIGKILL).我的问题是 - 是否有任何编程方式(一些系统调用)来通知服务器我已完成发送 - 而不是服务器始终检查 \0\0 ?服务器在客户端/侦听套接字上使用 poll() 来检测是否有要读取的内容/新连接请求,顺便说一句.
I have a tiny little TCP app where many clients connect to a server, send data to it (via write() - they are also sending message size) and then exit. I have the clients send \0\0 to the server when done sending - and I make it so that if the server gets a zero from read() then it knows something went wrong in the client (like SIGKILL). My question is - is there any programmatic way (some sys call) to notify the server that I am done sending - instead of the server checking always for \0\0 ? Server uses poll() on clients/listening socket to detect if there is something to read/new connection request, btw.
我应该发送信号吗?但是我怎么知道哪个描述符要停止轮询呢?
Should I send a signal ? But how do I know which descriptor to stop polling then ?
我阅读了这个 但答案或多或少是我现在使用的
I read this but the answers there are more or less what I use now
推荐答案
在应用程序级别执行此操作(例如,在执行时使用 \0\0
)是正确的方法如果您的协议比单个请求/响应模型更复杂一些.
Doing it at the application level (e.g. using \0\0
as you're doing it) is the correct way to do if your protocol is a bit more complex that a single request/response model.
例如,HTTP 1.0 在单个请求/响应后立即关闭连接:客户端发送其请求命令,服务器响应其响应并关闭连接.
HTTP 1.0, for example, closes the connection straight after a single request/response: the client sends its request command, the server replies with its response and closes the connection.
在具有更复杂交换的协议中,有特定的命令来指示消息的结束.例如,SMTP 和 POP3 是以行分隔的.当通过 SMTP 发送电子邮件的内容时,您在一行中使用 .
指示消息的结尾(实际消息中的 .
被转义为 .
>...).您还会收到诸如 QUIT
之类的命令来表示您已完成.
In protocols where you have a more complex exchange, there are specific commands to indicate the end of a message. SMTP and POP3, for example, are line-delimited. When sending the content of an e-mail via SMTP, you indicate the end of the message using .
on a single line (.
in the actual message is escaped as ..
). You also get commands such as QUIT
to indicate you're done.
在 HTTP 1.1 中,请求标头集以空行终止(例如 GET/HTTP/1.1
+ 一行上的每个标头 + 空行),因此服务器知道在哪里请求的结尾是.HTTP 1.1 中的响应然后使用 Content-Length
标头(在响应正文结束时发出信号)或使用 chunked transfer encoding 本质上插入了许多分隔符来指示是否有更多数据到来(通常,当服务器不知道数据大小时使用它提前).(具有正文的请求也使用相同的标头来指示请求何时结束.)
In HTTP 1.1, the set of request headers is terminated by an empty-line (e.g. GET / HTTP/1.1
+ each header on a line + an empty line), so the server knows where the end of the request is. The responses in HTTP 1.1 then use either a Content-Length
header (to signal when the end of the response body is going to be) or use chunked transfer encoding which essentially inserts a number of delimiters to indicated whether there's more data coming (usually, it's used when the data size isn't known by the server in advance). (Requests that have a body also use the same headers to indicate when the request ends.)
否则服务器很难知道它何时完成读取,因为通常无法检测 socket 断开连接(或者更确切地说,如果它仍然连接,即使客户端没有发送任何数据).通过在应用程序级别发送一些分隔符或长度指示符,您可以避免此类问题(或者可以检测何时出现问题/超时).
It's otherwise difficult for the server to know when it's done reading, since it's generally not possible to detect whether a socket is disconnected (or rather, if it's still connected even though the client isn't sending any data). By sending some delimiter or length indicator at the application-level, you avoid this sort of problem (or can detect when there's a problem/timeout).
这篇关于Unix 中的 TCP 套接字 - 通知服务器我已完成发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!