socket.shutdown 与 socket.close
Posted
技术标签:
【中文标题】socket.shutdown 与 socket.close【英文标题】:socket.shutdown vs socket.close 【发布时间】:2010-09-29 09:58:21 【问题描述】:我最近看到了一些看起来像这样的代码(当然 sock 是一个套接字对象):
sock.shutdown(socket.SHUT_RDWR)
sock.close()
在套接字上调用shutdown然后关闭它的目的到底是什么?如果有所不同,则此套接字正在用于非阻塞 IO。
【问题讨论】:
【参考方案1】:这是explanation:
一旦不再需要套接字, 调用程序可以丢弃 通过应用关闭子例程进行套接字 到套接字描述符。如果一个 可靠的传递套接字有数据 关闭时与之相关联 地方,系统继续尝试 数据传输。但是,如果数据是 仍未送达,系统丢弃 数据。应否申请 程序对任何未决的程序都没有用处 数据,它可以使用关机 套接字上的子程序之前 关闭它。
【讨论】:
【参考方案2】:关机和关闭说明:Graceful shutdown (msdn)
关闭(在您的情况下)向连接的另一端表明没有进一步读取或写入套接字的意图。然后关闭释放与套接字关联的所有内存。
省略关闭可能会导致套接字在操作系统堆栈中逗留,直到连接被正常关闭。
IMO 名称“shutdown”和“close”具有误导性,“close”和“destroy”会强调它们的区别。
【讨论】:
并不向对方表明没有进一步阅读的意图。关闭读取不会向对等方发送任何内容。【参考方案3】:有一些关闭的味道:http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx。 *nix 类似。
【讨论】:
关机有一种“味道”,有两种选择,可以组合使用。这里没有回答实际问题。【参考方案4】:调用close
和shutdown
对底层套接字有两种不同的影响。
首先要指出的是,套接字是底层操作系统中的资源,多个进程可以拥有同一个底层套接字的句柄。
当您调用close
时,它会将句柄计数减一,如果句柄计数达到零,则套接字和关联的连接将通过正常关闭过程(有效地向对等方发送 FIN / EOF)和套接字已解除分配。
这里要注意的是,如果句柄计数没有达到零,因为另一个进程仍然有套接字的句柄,那么连接不会关闭,套接字也不会被释放。
另一方面,调用shutdown
进行读写会关闭底层连接并向对等方发送一个FIN / EOF,而不管有多少进程拥有套接字句柄。但是,它不会释放套接字,之后您仍然需要调用 close。
【讨论】:
很好的答案,我从不费心去了解shutdown()
做了什么:)
读操作的shutdown() 会导致它发送一个FIN 数据包吗?即关机(sock_fd, 1);
总是拨打.shutdown()
并在下一行拨打.close()
是否明智?或者之间应该有延迟?
@Luc 完全取决于你在做什么。
@Luc 只要没有其他进程拥有套接字句柄,只要关闭就可以了。【参考方案5】:
Shutdown(1) ,强制套接字不发送更多数据
这在
中很有用1- 缓冲区刷新
2- 奇怪的错误检测
3- 安全防护
让我再解释一下,当您将数据从 A 发送到 B 时,不能保证是 发送到 B ,只保证发送到 A os 缓冲区, 然后将其发送到 B os 缓冲区
因此,通过在 A 上调用 shutdown(1),您会刷新 A 的缓冲区并引发错误 如果缓冲区不为空,即:数据尚未发送到对等方
但是这是不可逆转的,所以你可以在你完全之后再做 发送了您的所有数据,并且您希望确保它至少在对等方 操作系统缓冲区
【讨论】:
关机不会强制刷新。缓冲情况不变。如果缓冲区不为空,则不会引发错误。 FIN 仅仅排在待处理数据的后面。答案完全错误。【参考方案6】:上面这段代码是不是错了?
在shutdown 调用之后直接调用close 可能会使内核丢弃所有传出缓冲区。
根据 http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable 需要在关机和关闭之间等待,直到读取返回 0。
【讨论】:
不正确。如果连接已重置,内核只会丢弃传出缓冲区,如果本地应用程序尚未读取所有已到达的待处理入站数据,或者如果对等点与 SO_LINGER 混淆,则可能会发生这种情况,他们不应该这样做.也没有必要睡觉,甚至在关闭之前也不需要调用shutdown。关于这件事有很多错误信息。【参考方案7】:在 Socket Programming HOWTO (py2/py3) 中提到过
断开连接
严格来说,您应该在
close
之前在套接字上使用shutdown
。shutdown
是对另一端套接字的建议。根据您传递的参数,它可能意味着“我不再发送,但我仍然会听”,或“我不听,再见! ”。 然而,大多数套接字库都习惯于程序员忽略使用这条礼仪,通常close
与shutdown(); close()
相同。 所以在大多数情况下,不需要显式关闭。...
【讨论】:
此信息不正确。只有在以下情况下才需要关闭套接字以进行写入:(1)您已经分叉了该进程并且确实希望现在发送 FIN,或者(2)您正在进行相互读取 - EOS 协议,使得两个对等方同时关闭。否则close()
就足够了。应该更正 Python 文档。以上是关于socket.shutdown 与 socket.close的主要内容,如果未能解决你的问题,请参考以下文章