Python: минимальный каркас websocket сервера

Из «коробки» в этом каркасе работа в потоках для обработки каждого сообщения. Собрано на основе пакета websockets.

Все клиенты хранятся в массиве clients. При отключении клиента — из массива он удаляется.

#!/usr/bin/env python3
#encoding: utf-8
import asyncio
import sys
import os
import websockets
from threading import Thread

# массив клиентов
clients=[]

# отправляем сообщение
def SendMessage(connect, message):
    asyncio.run(connect["connect"].send(message))

def MessageProcessing(websocket,message):
  # выясняем от кого обрабатываем сообщения
  for connect in clients:
     if connect["connect"] == websocket:
        print(f"IN: {message}")
        SendMessage(connect,"Hello")

# новый клиент
async def OnNewClient(websocket, path):
        requested_protocols = websocket.request_headers['Sec-WebSocket-Protocol']
        patch = path.strip('/')
        print(f"Новый клиент: {requested_protocols},{patch}")
        try:
          pasket = {}
          pasket["connect"] = websocket
          pasket["host"] = websocket.request_headers['Host']
          clients.append(pasket)
          async for message in websocket:
               th = Thread(target=MessageProcessing, args=(websocket,message,))
               th.start()
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(f"Прерывание: {e} ({fname},строка: {exc_tb.tb_lineno})")

        finally:
            print(f"соединение закрыто..")
            for connect in clients:
                if connect["connect"]==websocket:
                    clients.remove(connect)

async def main():
  async with websockets.serve(OnNewClient, "0.0.0.0", 35609,subprotocols=["virtual"]):
    print("сервер стартовал и ждёт клиентов")
    await asyncio.Future()

asyncio.run(main())