Why am I getting a ConnectionResetError here?
You're getting the exception because you're trying to write some data back to the client on the server-side, but the client is closing the socket
immediately after sending in the 'echo'
, without actually receiving the response from the server. If a socket connection is closed while there is unreceived data on the wire, you'll get an error on the sending side, so that you know the remote side may not have received whatever you last sent.
The problem goes away if you add a call to socket.recv(1024)
on the client-side prior to calling socket.close()
, so that the client waits for a response from the server before closing the socket. You could also just use a try
/except
around the write call on the server-side if you just want to gracefully handle the exception, even when the client does the wrong thing.
gnargnagnar
Updated on July 26, 2022Comments
-
gnargnagnar almost 2 years
I am new to Python 3 and am playing around with asyncio. Thereby, I am experiencing a strange behavior with the following server-side code:
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()
When I run this client code (EDIT: client code is entered manually into an IPython session, the server definitely has time to write before I close the socket)...
import socket client = socket.create_connection(('localhost', 8888)) client.sendall('echo\n'.encode()) client.close()
... I get an error traceback from the server:
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
The issue must be somehow in relation with
writer.write
, because when I call the following client code (which makes the server skip the writing), there is no error:import socket client = socket.create_connection(('localhost', 8888)) client.sendall('foo\n'.encode()) client.close()
The corresponding server log:
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.
What am I missing? Am I using asyncio incorrectly?
Thanks!