【问题标题】:how to reproduce "Connection reset by peer"如何重现“对等方重置连接”
【发布时间】: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


【解决方案1】:

您可以将套接字“linger”选项设置为 0 并关闭套接字以发送重置。更新你的服务器

import socket
import struct
import time

# tcp_server.py
def handler(client_sock, addr):
    try:
        print('new client from %s:%s' % addr)
        time.sleep(1)
    finally:
        client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
            struct.pack('ii', 1, 0))
        client_sock.close()   # close current connection directly

if __name__ == '__main__':

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', 5500))
    sock.listen(5)

    while 1:
        client_sock, addr = sock.accept()
        handler(client_sock, addr)

并运行此客户端

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('', 5500))
print(sock.recv(1024))

我明白了

Traceback (most recent call last):
  File "tcpclient.py", line 5, in <module>
    print(sock.recv(1024))
ConnectionResetError: [Errno 104] Connection reset by peer

【讨论】:

  • 谢谢。您的代码确实引发了异常。然后另一个问题:为什么sendrecv 在这方面表现不同
猜你喜欢
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多