【发布时间】:2016-11-24 01:52:46
【问题描述】:
我已经了解了 tcp 中两个臭名昭著的错误之间的区别:
[Errno 54] Connection reset by peer[Errno 32] Broken pipe
这两个错误都是 tcp 连接的一侧因未知原因关闭,而另一侧仍在与它通信。
- 当对方
write有东西时,Broken pipe被抛出 - 当对方
read有东西时,Connection reset by peer被抛出
我能够使用下面的 Python 代码重现 Broken pipe。
# tcp_server.py
def handler(client_sock, addr):
try:
print('new client from %s:%s' % addr)
finally:
client_sock.close() # close current connection directly
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 5500))
sock.listen(5)
while 1:
client_sock, addr = sock.accept()
handler(client_sock, addr)
至于客户,
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.connect(('', 5500))
>>> sock.send('a')
1
>>> sock.send('a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
socket.error: [Errno 32] Broken pipe
当客户端第一次send,一个RST数据包从服务器发送到客户端,从这一刻起,send将一直抛出Broken pipe。
以上一切都在我的理解范围内。但是,当客户端从服务器读取时,它总是返回空字符串而不是 throw Connection reset by peer
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.connect(('', 5500))
>>> sock.recv(1024)
''
>>> sock.recv(1024)
''
>>> sock.recv(1024)
''
>>> sock.recv(1024)
我对此感到困惑,或者一般如何重现Connection reset by peer?
【问题讨论】:
-
您使用此处概述的 SO_LINGER 选项发送重置:stackoverflow.com/a/6440364/642070
-
@tdelaney 仍然接收空字符串
-
它对我有用。我不得不在服务器中添加一个短暂的等待,这样 RST 就不会随着连接返回。
标签: python sockets networking tcp network-programming