在python

时间:2016-02-03 10:25:33

标签: python sockets tcp

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

2 个答案:

答案 0 :(得分:1)

当您必须通知远程客户端不再发送数据时,

shutdown非常有用。您可以在shutdown()参数中指定要关闭的半通道。

最常见的是,您希望通过调用shutdown(1)来关闭TX半通道。在TCP级别,它发送一个FIN数据包,如果在read()上阻塞,远程端将接收0个字节,但远程端仍然可以发回数据,因为RX半通道仍处于打开状态。

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

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

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

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

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

答案 1 :(得分:0)

根据python documentation说:

  

严格地说,你之前应该在套接字上使用shutdown   你关闭它。关闭是对另一个套接字的建议   结束。根据您传递的参数,它可能意味着“我不会去   再发送,但我仍会听“,或者”我不是在听,好   甩掉包袱!”。但是,大多数套接字库都习惯于程序员   忽略了使用通常接近的礼仪   与shutdown()相同;关()。所以在大多数情况下,一个明确的   不需要关机。

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