My asyncio server won't shut down if a client has connected even if the client closes the socket. Why won't it stop? If a client does not connect within 10 seconds it shuts down and the program closes.
My procedure:
Result:
I found that adding writer.close()
in the clientHandler
solved the issue but why? Where is this documented/explained?
# server
from os import path as ospath
import asyncio
import socket as Socket
import logger as log
logger = log.getLogger(fileName=ospath.join('log', 'server.log'), initialize=True)
class Client():
def __init__(self, socket:Socket=None, addr:tuple=None) -> None:
self.socket = socket
self.addr = addr
self.connected = False
class App():
def __init__(self) -> None:
self.quit = False
self.clients = []
async def clientHandler(reader, writer):
logger.info('client handler starting')
async def main():
logger.info("server app starting")
app = App()
# start socket server
ipaddr = Socket.gethostbyname(Socket.gethostname())
port = 32843
logger.info(f'starting socket server ({ipaddr}:{port})')
server = await asyncio.start_server(clientHandler, ipaddr, port=32843)
logger.info('waiting for client to connect...')
await asyncio.sleep(10)
logger.info('closing server')
server.close()
await server.wait_closed()
logger.info('server closed')
if __name__ == '__main__':
asyncio.run(main())
# client
import socket
dest_ip = socket.gethostbyname(socket.gethostname())
dest_port = 32843
encoder = "utf-8"
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((dest_ip, dest_port))
client_socket.shutdown(socket.SHUT_RDWR)
client_socket.close()
The client closes the socket, but the TCP connection remains half-closed, because the server does not close its end. Thus the server cannot consider the client disconnected.
A half-closed connection happens when one side sends EOF. The other side can continue to send data before it sends an EOF too.
You need to add writer.close()
to the clientHandler()
to fix it.
Side note: server.wait_closed()
was slightly broken before Python 3.12.1 and it is probably not possible to reproduce the issue on older versions.