Мне нужно поместить серверный и клиентский код в один скрипт для автоматизации. Моя проблема в том, что socket.accept()
- это блокирующий вызов, и скрипт зависает, прежде чем я могу вызвать клиента. [...] Я интуитивно чувствую, что могу сделать это с помощью модуля asyncio
Asyncio действительно позволяет легко запускать несколько задач «в фоновом режиме» (см. asyncio.create_task
) или «параллельно» (см. asyncio.gather
).
На самом деле, поскольку API start_server
запускает сервер «в фоновом режиме» для начала (что-то вроде того, как сервер разветвляется, чтобы демонизировать себя, и вам не нужно добавлять &
при запуске из оболочки) вам даже не нужно делать ничего особенного для параллельного запуска клиента и сервера - просто запустите сервер, дождитесь клиентской сопрограммы и остановите сервер.
В качестве примера, начиная с примеров клиента / сервера echo из документации , я быстро пришел к чему-то вроде этого:
import asyncio
async def connect():
print('connecting...')
reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
writer.write(b'hello world')
data = await reader.read(100)
assert data == b'hello world'
writer.close()
await writer.wait_closed()
print('closed connection')
return data
async def handle_client(reader, writer):
print('incoming connection')
while True:
data = await reader.read(100)
if data == b'':
break
writer.write(data)
await writer.drain()
print('incoming connection closed')
async def main():
server = await asyncio.start_server(handle_client, '127.0.0.1', 8888)
print('server now set up')
await connect()
server.close()
await server.wait_closed()
asyncio.run(main())