(original) (raw)
# coding=utf-8 import uvloop import asyncio from signal import ( signal, SIGINT, ) import socket import logging import sys logging.basicConfig(format='%(asctime)s [%(process)d] [%(levelname)s] [%(filename)s:%(lineno)d] : %(message)s') logger = logging.getLogger(__name__) USE_UVLOOP = False CALL_REMOVE_READING_BEFORE_CLOSE = False async def foo(): loop = asyncio.get_event_loop() # start server sock_server = socket.socket() sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock_server.bind(('127.0.0.1', 9080)) sock_server.listen(10) sock_server.setblocking(0) # client start and send some data sock_client = socket.socket() sock_client.setblocking(0) await loop.sock_connect(sock_client, ('127.0.0.1', 9080)) await loop.sock_sendall(sock_client, b'a') # server accept and recv data sock_server_worker, _ = await loop.sock_accept(sock_server) sock_server_worker.setblocking(0) if not USE_UVLOOP: try: loop._selector.get_key(sock_server_worker.fileno()) except KeyError: pass data = await loop.sock_recv(sock_server_worker, 1) assert data == b'a' # assume server worker call sock_recv and cancel future(assume client failed to send other data in time) fut = loop.sock_recv(sock_server_worker, 1) print(['first worker fd', sock_server_worker.fileno()]) fut.cancel() await asyncio.sleep(0) if CALL_REMOVE_READING_BEFORE_CLOSE: loop.remove_reader(sock_server_worker.fileno()) sock_server_worker.close() # client notice server close the connection data = await loop.sock_recv(sock_client, 1) assert data == b'' sock_client.close() # another client and send data sock_client = socket.socket() sock_client.setblocking(0) await loop.sock_connect(sock_client, ('127.0.0.1', 9080)) async def client_async_send_req(): await asyncio.sleep(0.1) await loop.sock_sendall(sock_client, b'a') loop.create_task(client_async_send_req()) # accept and call sock_recv, but this time sock recv will hang. # because the new sock_server_worker has same fd as previous sock_server_worker, # though we call sock_recv, loop will not register fd again. # We should call loop.remove_reader before closing socket. sock_server_worker, _ = await loop.sock_accept(sock_server) sock_server_worker.setblocking(0) print(['second worker fd', sock_server_worker.fileno()]) if not USE_UVLOOP: try: print(['reader is already registered', loop._selector.get_key(sock_server_worker.fileno())]) except KeyError: pass print('start blocking') try: await asyncio.wait_for(loop.sock_recv(sock_server_worker, 1), 1) except: print('timeout') else: print('we are fine') loop.stop() def main(): if USE_UVLOOP: asyncio.set_event_loop(uvloop.new_event_loop()) loop = asyncio.get_event_loop() loop.set_debug(True) signal(SIGINT, lambda s, f: sys.exit(2)) # loop.create_task(conn_t()) # noinspection PyBroadException try: loop.create_task(foo()) loop.run_forever() except: loop.stop() if __name__ == '__main__': main()