为什么我在这里得到一个ConnectionResetError?

2024-05-20 20:45:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Python 3的新手,正在使用asyncio。因此,我遇到了一个奇怪的行为,服务器端代码如下:

import asyncio


@asyncio.coroutine
def handle_client(reader, writer):
    print('Client connected.')
    client_connected = True
    while client_connected:
        print('Waiting for client event.')
        line = yield from reader.readline()
        if line:
            print('Got: {}'.format(line))
            if line.decode() == 'echo\n':
                print('Sending back echo.')
                writer.write(line)
            else:
                print('Not sending back anything.')
        else:
            print('Client disconnected.')
            client_connected = False


if __name__ == '__main__':
    asyncio.async(asyncio.start_server(handle_client, 'localhost', 8888))
    asyncio.get_event_loop().run_forever()

当我运行这个客户机代码时(编辑:客户机代码是手动输入到IPython会话中的,在我关闭套接字之前,服务器肯定有时间编写)。。。

import socket
client = socket.create_connection(('localhost', 8888))
client.sendall('echo\n'.encode())
client.close()

。。。我从服务器获得错误回溯:

C:\Users\Gnar\Anaconda3\python.exe C:/Users/Gnar/Code/echo.py
Client connected.
Waiting for client event.
Got: b'echo\n'
Sending back echo.
Waiting for client event.
Task exception was never retrieved
future: <Task finished coro=<handle_client() done, defined at C:/Users/Gnar/Code/echo.py:4> exception=ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None)>
Traceback (most recent call last):
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\tasks.py", line 234, in _step
    result = coro.throw(exc)
  File "C:/Users/Gnar/Code/echo.py", line 10, in handle_client
    line = yield from reader.readline()
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\streams.py", line 425, in readline
    yield from self._wait_for_data('readline')
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\streams.py", line 393, in _wait_for_data
    yield from self._waiter
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\futures.py", line 386, in __iter__
    yield self  # This tells Task to wait for completion.
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\tasks.py", line 287, in _wakeup
    value = future.result()
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\futures.py", line 275, in result
    raise self._exception
  File "C:\Users\Gnar\Anaconda3\lib\asyncio\selector_events.py", line 662, in _read_ready
    data = self._sock.recv(self.max_size)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

这个问题一定与writer.write有关,因为当我调用以下客户机代码(这使服务器跳过写入)时,没有错误:

import socket
client = socket.create_connection(('localhost', 8888))
client.sendall('foo\n'.encode())
client.close()

相应的服务器日志:

C:\Users\Gnar\Anaconda3\python.exe C:/Users/Gnar/Code/echo.py
Client connected.
Waiting for client event.
Got: b'foo\n'
Not sending back anything.
Waiting for client event.
Client disconnected.

我错过了什么?我使用异步是否不正确?

谢谢!


Tags: inpyechoclienteventasyncioforlib
1条回答
网友
1楼 · 发布于 2024-05-20 20:45:53

您得到异常是因为您试图将一些数据写回服务器端的客户机,但是客户机在发送'echo'后立即关闭socket,而实际上没有从服务器接收响应。如果在线路上有未接收到的数据时关闭了套接字连接,则发送端将出现错误,这样您就知道远程端可能没有收到您上次发送的任何数据。

如果在调用socket.close()之前向客户端的socket.recv(1024)添加一个调用,以便客户端在关闭套接字之前等待服务器的响应,那么问题就会消失。如果您只想优雅地处理异常,甚至在客户端做了错误的事情时,也可以在服务器端的write调用周围使用try/except

相关问题 更多 >