Асинхронное управление подключенными клиентами при непрерывной отправке данных в Python - PullRequest
0 голосов
/ 25 марта 2020

У меня есть встроенный сервер Python, который использует Sani c и веб-сокеты для обычной передачи данных клиентам:

@app.websocket("/")
async def websocket(request, ws):
  app.ws_clients.add(ws)
  await ws.send(json.dumps("hello from climate server!"))

  while True:
    try:

      data = dict()
      time_of_reading = time.ctime(time.time())
      data['climateData'] = sensor.read_data()
      data['systemData'] = get_system_data()
      data['timestamp'] = time_of_reading

      await broadcast(json.dumps(data))
      time.sleep(10) # changing this to asyncio.sleep() causes the msgs to send sporatically

    except KeyboardInterrupt:
      sensor.clear()
      pass

if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8080, workers=1, debug=False)

и мою функцию широковещания, которая пытается отправить сообщение или удаляет клиент из app.ws_clients, если есть ошибка ConnectionClosed:

async def broadcast(message):
  for ws in app.ws_clients:
    try:
      await ws.send(message)
      print('attempting data send') # this line runs, but the clients don't receive the messages

    except websockets.ConnectionClosed:
      clients_to_remove.add(ws)

    except KeyboardInterrupt:
      sensor.clear()
      pass

  if (len(clients_to_remove) > 0):
    await remove_dead_clients(clients_to_remove)

async def remove_dead_clients(clients_to_remove):
  for client in clients_to_remove:
    app.ws_clients.remove(client)

  clients_to_remove.clear()

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

Я использую эту функцию широковещания с другого сервера, который я написал, и она прекрасно работает там. Разница с этим в том, что он отправляет данные только тогда, когда клиент запрашивает их. Я чувствую, что проблема в том, что asyn c не может одновременно обрабатывать и удалять клиентов. Я попытался изменить time.sleep() на asyncio.sleep(), но это позволило только успешно отправлять сообщения десятки за раз, а потом вообще ничего не делать.

Есть ли шаблон, который я мог бы реализовать, который бы соответствовал моим нужно, куда я могу отправлять сообщения в бесконечном l oop, а также асинхронно управлять подключенными клиентами?

1 Ответ

0 голосов
/ 25 марта 2020

Для тех, кто случайно столкнется с этим в будущем - я забыл использовать ключевое слово await до asyncio.sleep().

...