146

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

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

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

4

7 回答 7

272

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

首先要指出的是,套接字是底层操作系统中的一种资源,多个进程可以拥有同一个底层套接字的句柄。

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

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

另一方面,调用shutdown读取和写入会关闭底层连接并向对等方发送 FIN / EOF,而不管有多少进程拥有套接字的句柄。但是,它不会释放套接字,您仍然需要在之后调用 close。

于 2009-02-28T21:58:05.953 回答
49

这是一种解释

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

于 2009-01-03T21:10:08.210 回答
19

关闭和关闭的解释:Graceful shutdown (msdn)

关闭(在您的情况下)表明连接的另一端没有进一步读取或写入套接字的意图。然后关闭释放与套接字关联的所有内存。

省略关闭可能会导致套接字在操作系统堆栈中逗留,直到连接正常关闭。

IMO 名称“关闭”和“关闭”具有误导性,“关闭”和“销毁”会强调它们的区别。

于 2009-01-04T01:28:29.593 回答
9

它在 Socket Programming HOWTO ( py2 / py3 )中有提到

断开连接

严格来说,您应该先shutdown在套接字上使用close它。这shutdown是对另一端套接字的建议。根据您传递的参数,它可以表示“<em>我不再发送,但我仍然会听”,或“<em>我不听,再见!”。然而,大多数套接字库都习惯于程序员忽略使用通常 acloseshutdown(); close(). 所以在大多数情况下,不需要显式关闭。

...

于 2013-09-25T16:05:00.033 回答
4

上面这段代码是不是错了?

在关闭调用之后直接关闭调用可能会使内核丢弃所有传出缓冲区。

根据 http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable 需要在关机和关闭直到读取返回 0。

于 2010-04-09T08:21:53.857 回答
3

有一些关闭的味道:http: //msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx。*nix 类似。

于 2009-01-04T01:52:19.717 回答
0

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

这在

1- 缓冲区刷新

2-奇怪的错误检测

3- 安全防护

让我再解释一下,当您从 A 向 B 发送数据时,并不保证会发送到 B ,只保证会发送到 A os 缓冲区,然后再将其发送到 B os 缓冲区

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

但是,这是不可撤销的,因此您可以在完全发送所有数据之后执行此操作,并且您希望确保它至少在对等操作系统缓冲区中

于 2010-03-31T16:03:46.890 回答