socket.shutdown与socket.close


122

我最近看到了一些看起来像这样的代码(袜子当然是套接字对象):

sock.shutdown(socket.SHUT_RDWR)
sock.close()

在套接字上调用shutdown然后关闭它的目的是什么?如果有所不同,则此套接字用于非阻塞IO。

Answers:


38

这是一个解释

一旦不再需要套接字,调用程序就可以通过对套接字描述符应用close子例程来丢弃该套接字。如果在关闭时可靠的传输套接字具有与之关联的数据,则系统将继续尝试进行数据传输。但是,如果仍未交付数据,则系统将丢弃该数据。如果应用程序不使用任何暂挂数据,则可以在关闭套接字之前使用套接字上的shutdown子例程。


241

调用closeshutdown对基础套接字有两种不同的影响。

首先要指出的是,套接字是基础操作系统中的资源,并且多个进程可以具有同一基础套接字的句柄。

您打电话的时候 close它时,将句柄计数减一,如果句柄计数达到零,则套接字和关联的连接将通过正常的关闭过程(有效地将FIN / EOF发送到对等方)来释放套接字。

这里要注意的是,如果句柄计数没有达到零,因为另一个进程仍然具有套接字的句柄,则连接不会关闭并且套接字不会被释放。

另一方面,调用shutdown读写会关闭基础连接,并向对等方发送FIN / EOF,而不管套接字有多少个进程。但是,它不会取消分配套接字,您仍然需要在事后调用close。


很好的答案,我从来没有想过要做什么shutdown():)
Matt Joiner 2010年

2
shutdown()可以读取导致它发送FIN数据包吗?即shutdown(sock_fd,1);
ernesto 2014年

始终拨打电话.shutdown()并在下一行通话会很聪明.close()吗?还是应该在两者之间有延迟?
吕克2014年

@Luc完全取决于您在做什么。
罗伯特·S·巴恩斯

2
@Luc然后只要没有其他进程具有套接字的句柄就可以关闭它。
罗伯特·S·巴恩斯

17

关闭和关闭的说明:正常关闭(msdn)

关机(针对您的情况)表示连接的另一端不再有读写套接字的意图。然后关闭释放与套接字关联的所有内存。

忽略关闭可能会导致套接字在操作系统堆栈中徘徊,直到正常关闭连接为止。

在国际海事组织中,“关闭”和“关闭”这两个名称具有误导性,“关闭”和“破坏”将强调它们之间的差异。


它并不表示另一端没有进一步的阅读意图。关闭读取不会将任何内容发送给同级。
罗恩侯爵,

7

在Socket Programming HOWTO(py2 / py3)中已经提到了

断开连接

严格来说,应该先shutdown在套接字上使用close它。该shutdown是在另一端的咨询到插座。根据您传递的参数,它可能表示“ 我不再发送了,但我仍会听 ”,或“ 我不在听,很好的摆脱!”。但是,大多数套接字库都习惯于程序员忽略使用此礼节,通常a close与相同shutdown(); close()。因此,在大多数情况下,不需要显式关闭。

...


此信息不正确。仅在以下情况下需要关闭套接字以进行写入:(1)您已经分叉了该过程并且肯定要立即发送FIN 或者(2)您正在使用双向读取EOS协议,以使两个对等方都关闭与此同时。否则close()就足够了。Python文档应予以更正。
罗恩侯爵,

4

上面的代码难道不是错误的吗?

在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。关于这个问题,有很多错误的信息。
罗恩侯爵,


1

Shutdown(1),强制套接字no发送更多数据

这在

1-缓冲液冲洗

2-奇怪的错误检测

3-安全防护

让我解释更多,当您将数据从A发送到B时,不保证将其发送到B,仅保证将其发送到A os缓冲区,然后缓冲区又将其发送到B os缓冲区。

因此,通过在A上调用shutdown(1),您将刷新A的缓冲区,如果缓冲区不为空,则会引发错误,即:尚未将数据发送到对等方

但是,这是不可挽回的,因此您可以在完全发送完所有数据之后,并确保至少在对等os缓冲区中执行此操作


关机不会强制冲洗。缓冲情况不变。如果缓冲区不为空,则不会引发任何错误。FIN仅排队在未决数据后面。答案是完全错误的。
罗恩侯爵,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.