Python сокет сервер и клиент в одном скрипте - PullRequest
0 голосов
/ 02 июня 2019

У меня, казалось бы, простое задание, которое я не могу обернуть мозгами. Вот что мне нужно сделать. Используя модуль сокета, запустите сервер, используйте клиент для запуска соединения, остановите сервер, верните данные соединения - все в одном скрипте. Я могу сделать это, когда я запускаю два из двух терминалов, но мне нужно поместить серверный и клиентский код в один скрипт для автоматизации. Моя проблема в том, что socket.accept () является блокирующим вызовом, и скрипт зависает, прежде чем я могу вызвать клиента. Пробовал играть с socket.setblocking (False), но он все еще блокирует. Я интуитивно чувствую, что могу сделать это с помощью модуля asyncio, но у меня нет опыта работы с ним, и примеры, которые я видел, не соответствуют моей задаче. Большое спасибо.

1 Ответ

2 голосов
/ 02 июня 2019

Мне нужно поместить серверный и клиентский код в один скрипт для автоматизации. Моя проблема в том, что 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())
...