我试图从客户端套接字读取字节时尝试从loop.sock_recv函数捕获连接重置错误。我正在测试一种情况,当服务器在特定超时后关闭连接时,sock_recv(client_socket,max_rec)函数会按预期引发连接重置错误,但我无法在代码中捕获它。相反,如果我用try/finally替换try/except,则效果更好,但并不总是能给出预期的答案。
try:
done, pending = await asyncio.wait([loop.sock_recv(client_sock, max_rec)], timeout = 7)
except ConnectionResetError:
log.info(f"Got the connection reset which means the server socket closed the connection after {timeout} seconds")
is_connection_reset = True
日志是[[0m ERROR 16:43:05| asyncio - Task exception was never retrieved
[[36mtest-client_1 |^[[0m future: <Task finished name='Task-67' coro=<BaseSelectorEventLoop.sock_recv() done, defined at /usr/local/lib/python3.8/asyncio/selector_events.py:349> exception=ConnectionResetError(104, 'Connection reset by peer')>(base_events.py, line 1707)
[[36mtest-client_1 |[[0m Traceback (most recent call last):
[[36mtest-client_1 |[[0m File "/usr/local/lib/python3.8/asyncio/selector_events.py", line 368, in sock_recv
[[36mtest-client_1 |[[0m return await fut
[[36mtest-client_1 |[[0m File "/usr/local/lib/python3.8/asyncio/selector_events.py", line 379, in _sock_recv
[[36mtest-client_1 |[[0m data = sock.recv(n)
[[36mtest-client_1 |[[0m ConnectionResetError: [Errno 104] Connection reset by peer
最佳答案
您应该将asyncio.wait([...], timeout=7)
替换为asyncio.wait_for
:
try:
data = await asyncio.wait_for(
loop.sock_recv(client_sock, max_rec), 7)
except ConnectionResetError:
... handle connection reset
except asyncio.TimeoutError:
... handle timeout
asyncio.wait_for(x, 7)
和asyncio.wait([x], timeout=7)
之间的区别在于,如果超时,wait_for
将取消等待。另一方面,asyncio.wait()
将使其在后台运行(并在pending
集中返回它)。在您的情况下,最有可能发生的情况是
sock_recv
在超过7秒后会升起ConnectionResetError
。如所写,您的代码仅在前7秒内发生错误时处理该错误。如果稍后发生,它将在后台任务中引发并由默认异常处理程序报告。顺便提一句,您可能不应该直接使用
sock_recv
。这是一个低级API,只有新事件循环的实现者才需要关心。应用程序代码应改为使用 asyncio.open_connection
。
关于python - 如何从loop.sock_recv()函数捕获连接重置错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62839066/