如何关闭非阻塞套接字?
我相信,如果我们在非阻塞套接字上调用 close 系统调用,它会立即返回,那么如何处理响应?是否关闭? 换句话说,套接字系统调用 close 在非阻塞套接字上的行为是什么?
I believe that if we call close system call on a non-blocking socket it returns immediately, then how to handle the response? whether it is closed or not?
in other words what is the behavior of the socket system call close on a non-blocking socket?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
重要的不是套接字的阻塞状态,而是 SO_LINGER 选项。来自
getsockopt(2)
:也就是说,在
SO_LINGER
启用的情况下,TCP 套接字上来自close(2)
的错误将意味着内核无法在延迟间隔内传送数据(不包括其他错误,例如无效错误)文件描述符等)。挥之不去的残疾 - 你永远不知道。另请参阅 最终的SO_LINGER页面,或者为什么我的tcp不可靠。It's not the blocking state of the socket, it's the
SO_LINGER
option that matters. Fromgetsockopt(2)
:That is, with
SO_LINGER
enabled an error fromclose(2)
on TCP socket would mean that kernel was not able to deliver data within linger interval (not counting other errors like invalid file descriptor, etc.). With lingering disabled - you never know. Also see The ultimate SO_LINGER page, or why is my tcp not reliable.套接字始终关闭:连接可能仍在向对等方写入数据。但你的问题体现了一个谬误:如果你在任何套接字上调用 close() ,它都会立即返回。关闭和写入套接字是异步的。您可以按照其他答案使用 SO_LINGER 进行控制,尽管我怀疑这只适用于阻塞模式。如果您需要这样做,您可能应该在使用正 SO_LINGER 关闭之前将套接字重新置于阻塞模式。
The socket is always closed: the connection may still be writing to the peer. But your question embodies a fallacy: if you call close() on any socket it will return immediately. Closing and writing to a socket is asynchronous. You can control that with SO_LINGER as per the other answer, although I suspect that only applies to blocking mode. Probably you should put the socket back into blocking mode before closing with a positive SO_LINGER if that's what you need to do.
@user207421 - 你的答案是错误的。如果套接字处于阻塞模式,并且 TCP 窗口已满/写入缓冲区已满,则 close() 将阻塞,因为 FIN 数据包需要 SEQ 和 ACK 编号。如果是非阻塞套接字,您会得到 EAGAIN。
然而,当 no-lingering 打开时,close() 将发送 RST 数据包而不是 FIN,并且不使用 SEQ/ACK。 RST 数据包将立即发送,写缓冲区的内容将被简单丢弃。 SO_LINGER 与阻塞或非阻塞 modi 没有任何关系——实际上没有任何关系。
@user207421 - your answer is wrong. If the socket is in blocking mode, and the TCP window is full/the write buffer is full, close() WILL block because the FIN packet requires SEQ and ACK numbers. In case of a non blocking socket, you get EAGAIN.
However, with no-lingering turned on, close() will send not a FIN but RST packet and it does not use SEQ/ACK. RST packet will be sent immediately, and the contents of write buffer will be simply discarded. SO_LINGER has nothing - really nothing - to do with blocking or non-blocking modi.