【问题标题】:ConnectionResetError: [Errno 54] Connection reset by peerConnectionResetError:[Errno 54] 对等方重置连接
【发布时间】:2018-07-13 14:26:02
【问题描述】:

我正在阅读 > 并尝试第一个 bhnet.py 程序。

在一个终端上,我运行脚本

./bhnet.py -l -p 9999 -c

在另一个终端上,运行脚本

./bhnet.py -t localhost -p 9999

然后输入

<ctrl-D>

ls -alt
<ctrl-D>

第一个终端会返回

File "bhnet.py", line 186, in client_handler
cmd_buffer += client_socket.recv(1024).decode('utf-8')
ConnectionResetError: [Errno 54] Connection reset by peer

以下是程序的代码

def client_handler(client_socket):
    global upload
    global execute
    global command

    # check for upload
    if len(upload_destination):

        # read all the buffer and write to destination
        file_buffer = ""

        # keep reading til none is available
        while True:
            data = client_socket.recv(1024)

            if not data:
                break
            else:
                file_buffer += data

        # take the bytes and write them out
        try:
            file_descriptor = open(upload_destination,'wb')
            file_descriptor.write(file_buffer)
            file_descriptor.close()

            # acknowledge that file being wrote out
            client_socket.send(f"Successfully save file to {upload_destination}.\r \n")
        except:
            client_socket.send(f"Failed to save file to {upload_destination}.\r \n")

    # check for command execution
    if command:

        while True:
            #pop up a window
            client_socket.send(b"<BHP:#> ")

            # keep receiving data until \n
            cmd_buffer = ""
            while "\n" not in cmd_buffer:
                cmd_buffer += client_socket.recv(1024).decode('utf-8')
            response = run_command(cmd_buffer)
            client_socket.send(response)

我用谷歌搜索,甚至尝试升级 openssl,但这些都不起作用...

提前致谢!

【问题讨论】:

    标签: python-3.x sockets


    【解决方案1】:

    由于您不提供客户端代码,因此很难确定。但是,我相当有信心这正在发生:

    当您键入 Ctrl-D 时,您将给客户端的输入一个文件结尾。这导致客户端 close 它先前连接到服务器的套接字。这样做会导致客户端的操作系统向服务器发送 TCP FIN 数据包。 FIN 只告诉服务器客户端已完成发送数据;在正常的 TCP 会话终止中,无法告诉对等方该对等方可能不再发送任何数据。

    但是在客户端关闭其套接字之后,服务器正在尝试向客户端发送send。当您尝试在关闭的套接字上发送更多数据时,然后目标对等方的操作系统发送 TCP RST 数据包。这实际上并没有在send 上报告给服务器,因为当数据被复制到内核时,send 函数调用已经完成——而RST 可能在几毫秒后被内核接收到实际上是向对端发送了一个数据包。

    因此,该条件将在套接字上的下一个操作中报告,此处为recv。因此,您的程序会返回一个 ECONNRESET 错误,python 会将其转换为 ConnectionResetError 异常。

    换句话说:

    Client            Server
    ------            ------
    close()
            FIN =>    <OS receives FIN>
                      send(data)
            <= "data"
            RST =>
                      recv
                      <ECONNRESET>
    

    还有一件事:根据确切的时间,您在该循环中对recv 的第一次调用实际上可能会得到一个文件结束指示符(即零字节)。但是,您并没有对此进行检查,只要缓冲区中没有换行符,您就一直调用recv。你真的应该检查你是否从recv 得到一个零字节字符串,并在这种情况下终止你的循环。

    一旦您在套接字上获得了文件结束指示符,您将永远将换行符添加到缓冲区中。如果客户端在关闭套接字之前确实接收到了您发送给它的数据,那么不会发送RST。在这种情况下,您的 recv 循环可能会永远运行,连续返回零字节但永远找不到换行符。

    【讨论】:

      猜你喜欢
      • 2017-04-12
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      相关资源
      最近更新 更多