我有以下代码,在 linux / mac 、远程和本地计算机上使用 python2.7 和 python3.5 进行了测试:
import socket
import time
s = socket.socket()
s.connect(("127.0.0.1", 8080))
s.sendall(b'first')
time.sleep(20)
s.sendall(b'should fail')
在另一边我有一个“服务器”正在运行netcat -l -p8080
我一看到first
,我杀死 netcat 命令
但是,那s.sendall
不会引发任何异常,为什么会这样?
编辑:注意做s.sendall
再一次然后引发异常
import socket
import time
s = socket.socket()
s.connect(("127.0.0.1", 8080))
s.sendall(b'first')
time.sleep(20)
s.sendall(b'should fail')
s.sendall(b'now it really fails')
因为你的 python 代码所代表的客户端还不知道服务器的套接字已关闭并消失。将 TCP 连接视为两个独立的通道:每个方向一个。 TCP 协议允许每一方在自己选择的时间关闭连接的发送方。并且 TCP 无法向对方表明未来向另一个方向发送的数据将不被接受。
更详细地说... TCP 会话的普通终止涉及each端发送数据包FIN
标志设置。这表明对等方发送FIN
不会再发送任何数据。确实如此not表明接收者FIN
数据包可能不再发送任何数据。
所以,这里发生的事情是,当你杀了netcat
, a FIN
数据包从服务器端发送到客户端(并由网络堆栈代表客户端确认)。这会关闭套接字的服务器=>客户端方向。然而,就客户端所知,client=>server 方向仍然可用。稍后,当您的客户端尝试发送数据时,将发送包含该数据的数据包。现在,服务器端的网络堆栈立即响应,通过发送一个消息来告诉客户端服务器不再存在。RST
包。然而,你的sendall
函数调用在收到时早已完成。
因此,如果您的客户再睡一秒钟(或者实际上只是一小部分秒),然后尝试another发送,后续发送would引发异常。
创建整个会话的数据包捕获并使用wireshark对其进行研究可能会很有启发。在调用 python 代码之前在另一个窗口中运行此命令(然后使用 Ctrl-C 终止):
sudo tcpdump -i lo -w /tmp/f.pcap port 8080
也可以使用wireshark来捕获,指定相同的port 8080
作为捕获过滤器——或者tcp.port == 8080
作为显示过滤器。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)