【问题标题】:Proper way to close tcp sockets in python在python中关闭tc​​p套接字的正确方法
【发布时间】:2016-05-12 11:50:17
【问题描述】:

我目前正在使用 Python 上的服务器 + 客户端组合,并且正在使用 TCP 套接字。从我知道的网络类中,TCP 连接应该逐步关闭,首先一方发送信号,它想要关闭连接并等待确认,然后另一方也这样做。之后,socket就可以安全关闭了。
我在 python 文档函数socket.shutdown(flag) 中看到过,但我看不到它如何用于这个标准方法,理论上关闭 TCP 套接字。据我所知,它只会阻止阅读、写作或两者兼而有之。
在python中关闭TCP套接字的最好、最正确的方法是什么?是否有关闭信号的标准函数或者我需要自己实现它们?

【问题讨论】:

标签: python sockets tcp


【解决方案1】:

当您必须通知远程客户端不再发送数据时,shutdown 很有用。您可以在shutdown()参数中指定要关闭哪个半通道。

最常见的情况是,您希望通过调用 shutdown(1) 来关闭 TX 半通道。在TCP层面,它发送一个FIN数据包,如果在read()上阻塞,远端会收到0字节,但远端仍然可以发回数据,因为RX半通道仍然打开。

一些应用程序协议使用它来表示消息的结束。其他一些协议根据数据本身找到 EOM。例如,在交互式协议中(消息被多次交换),可能没有机会或不需要关闭半通道。

在 HTTP 中,shutdown(1) 是客户端可以用来表示 HTTP 请求已完成的一种方法。但是 HTTP 协议本身嵌入了数据,可以检测请求的结束位置,因此多个请求的 HTTP 连接仍然是可能的。

我不认为在 close() 之前调用 shutdown() 总是必要的,除非您需要显式关闭半通道。如果您想停止所有通信, close() 也会这样做。调用shutdown()而忘记调用close()更糟糕,因为文件描述符资源没有被释放。

来自 Wikipedia:“在 SVR4 系统上使用 close() 可能会丢弃数据。在这些系统上可能需要使用 shutdown() 或 SO_LINGER 以保证所有数据的传递。”这意味着,如果您在输出缓冲区中有未完成的数据,则 close() 可以在 SVR4 系统上立即丢弃这些数据。 Linux、BSD 和基于 BSD 的系统(如 Apple)不是 SVR4, 会尝试在 close() 之后完整发送输出缓冲区。我不确定现在是否有任何主要的商业 UNIX 仍然是 SVR4。

再次以 HTTP 为例,在 SVR4 上运行的 HTTP 客户端使用 close() 不会丢失数据,因为它会在请求获得响应后保持连接打开。 SVR 下的 HTTP 服务器必须更加小心,在发送整个响应之后在 close() 之前调用 shutdown(2),因为响应将部分在输出缓冲区中。

【讨论】:

    【解决方案2】:

    根据 python documentation 说:

    严格来说,您应该先在套接字上使用shutdown 你关闭它。关闭是对另一个套接字的建议 结尾。根据你传递的论点,它可能意味着“我不去 再发送,但我还是会听”,或者“我没在听,很好 解脱!”。然而,大多数套接字库都为程序员所习惯 忽略使用通常关闭是的这种礼仪 与关机()相同;关闭()。所以在大多数情况下,显式 不需要关机。

    我认为关闭 TCP 连接最正确的方法是在关闭连接之前使用shutdown,因为close 不是原子的!这可能会产生一些错误。假设你使用close 函数没有shutdown 并且数据没有正确发送到服务器,同时python关闭连接并且服务器无法回复客户端,现在另一端的套接字可能无限期挂起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 2012-02-10
      • 2018-07-27
      相关资源
      最近更新 更多