Веб-сокеты Python отправляют клиенту и поддерживают соединение - PullRequest
0 голосов
/ 16 ноября 2018

Я использую Python Websockets: https://websockets.readthedocs.io/

У них есть простой пример клиент / сервер, где сервер возвращает ответ клиента один раз. Код выглядит так:

Клиентская сторона:

# WS client example

import asyncio
import websockets

async def hello():
    async with websockets.connect(
            'ws://localhost:8765') as websocket:
        name = input("What's your name? ")

        await websocket.send(name)
        print(f"> {name}")

        greeting = await websocket.recv()
        print(f"< {greeting}")

asyncio.get_event_loop().run_until_complete(hello())

Серверная сторона:

# WS server example

import asyncio
import websockets

async def hello(websocket, path):
    name = await websocket.recv()
    print(f"< {name}")

    greeting = f"Hello {name}!"

    await websocket.send(greeting)
    print(f"> {greeting}")

start_server = websockets.serve(hello, 'localhost', 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Я хочу настроить только на стороне сервера, чтобы при подключении к сокету он делал следующее:

  1. Отправить сообщение с подтверждением клиенту. например Hello Client! Please wait for your data.
  2. Поддерживать связь.
  3. Обработка некоторых данных, которая занимает некоторое время.
  4. После того, как данные завершили обработку, уведомите клиента о существующем соединении через веб-сокет. например Your data is here!

В документации по python websockets отсутствует пример кода, который делает это.

Ответы [ 2 ]

0 голосов
/ 29 июля 2019

Чтобы сохранить соединение открытым, не завершайте обработчик после обработки первого сообщения. Например, у вас может быть бесконечный цикл, который будет продолжать обрабатывать входящие сообщения до тех пор, пока клиент не закроет соединение:

async def hello(websocket, path):
    while True:
        try:
            name = await websocket.recv()
        except websockets.ConnectionClosed:
            print(f"Terminated")
            break

        print(f"< {name}")
        greeting = f"Hello {name}!"

        await websocket.send(greeting)
        print(f"> {greeting}")

В игре async вы можете await любую длительную операцию, как предложено здесь .

Однако вам нужно будет адаптировать как серверную, так и клиентскую части аналогичным образом. Ваш клиент также завершает работу после получения первого сообщения.

0 голосов
/ 16 ноября 2018

Предположительно, ваша функция, которая обрабатывает данные, блокирует, в противном случае вы просто await поместите их в сопрограмму.Простой подход заключается в использовании run_in_executor для запуска его в другом потоке и await в сопрограмме обработчика:

async def hello(websocket, path):
    loop = asyncio.get_event_loop()
    await websocket.send("Hello Client! Please wait for your data.")
    data = await loop.run_in_executor(None, get_data)
    await websocket.send("Your data is here!")
    await websocket.send(data)

def get_data():
    # something that takes a long time to calculate
    x = 19134702400093278081449423917**300000 % 256
    return bytes([x])
...