Python中websockets服务端给多线程发送消息

思路:

1.由于websockets创建服务端只能绑定一个端口,所以需要单独占用一个线程

2.消息中心需要独立出来,一边放一边取

模块功能都在下面,先运行Main.py,再运行websocket_client.py

修改websocket_client.py中data的信息,可以看到不同消息

一、消息处理中心 message_base.py

根据设备,创建储存设备消息,提取设备消息的功能

python 复制代码
from queue import Queue


class MessageBase:
    def __init__(self):
        self.data = dict()

    def add(self, device, data):
        if device in self.data:
            self.data[device].put(data)
        else:
            self.data[device] = Queue()
            self.data[device].put(data)

    def get(self, device):
        data_queue: Queue = self.data.get(device)
        if not data_queue or data_queue.empty():
            return None
        data = data_queue.get()
        return data


if __name__ == '__main__':
    mb = MessageBase()
    mb.add("a", "asdasd")
    mb.add("a", "11111111")
    print(mb.data)
    data = mb.get("a")
    print(data)

二、服务端:websocket_server.py

给消息中心存消息

python 复制代码
import asyncio
import json
import threading
import websockets
##
from message_base import MessageBase


class WebServer:
    def __init__(self, host, port, message_base: MessageBase):
        self.host = host
        self.port = port
        self.clients = []
        self.message_base = message_base

    async def echo(self, websocket, path):
        self.clients.append(websocket)
        client_ip, client_port = websocket.remote_address
        while True:
            try:
                recv_text = await websocket.recv()
                data = json.loads(recv_text)
                device = data.get("device")
                if device:
                    self.message_base.add(device, data)
                else:
                    continue
            except websockets.ConnectionClosed:
                print("ConnectionClosed...")  # 链接断开
                self.clients.remove(websocket)
                break
            except websockets.InvalidState:
                print("InvalidState...")  # 无效状态
                self.clients.remove(websocket)
                break
            except Exception as e:
                print(e)

    def connect(self):
        print("连接成功!")
        asyncio.set_event_loop(asyncio.new_event_loop())
        start_server = websockets.serve(self.echo, self.host, self.port)
        asyncio.get_event_loop().run_until_complete(start_server)
        asyncio.get_event_loop().run_forever()

    def run(self):
        t = threading.Thread(target=self.connect)
        t.start()
        print("已启动!")


if __name__ == '__main__':
    mb = MessageBase()
    ws = WebServer("192.168.6.28", 8001, mb)
    ws.run()

三、设备功能 device_function.py

每个设备对应的线程功能,可以同意也可以写多个功能

python 复制代码
class DeviceFunc:
    def __init__(self, device_name, data):
        self.device_name = device_name
        self.data = data

    def show_data(self):
        if self.data:
            print(self.device_name, "收到消息:", self.data.get("value"))

四、主线程 main.py

初始化所有功能,并运行主线程

python 复制代码
from message_base import MessageBase
from websocket_server import WebServer
from device_function import DeviceFunc


class MainThread:
    def __init__(self, message_base: MessageBase, websocket_server: WebServer, device_list):
        self.message_base = message_base
        self.websocket_server = websocket_server
        self.device_list = device_list

    def run_server(self):
        self.websocket_server.run()

    def run(self):
        self.run_server()
        while True:
            for device in self.device_list:
                try:
                    data = self.message_base.get(device)
                    df = DeviceFunc(device, data)
                    df.show_data()
                except Exception as err:
                    pass


if __name__ == '__main__':
    mb = MessageBase()
    ws = WebServer("192.168.6.28", 8000, mb)
    device_list = ["aa", "bb", "cc"]

    mt = MainThread(mb, ws, device_list)
    mt.run()

五、客户端

给服务端发送消息,测试用

python 复制代码
import json

import websocket


class WebClient:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.conn = None
        self.flag = False

    def connect(self):
        try:
            url = f"ws://{self.host}:{self.port}"
            self.conn = websocket.create_connection(url)
            self.flag = True
            print("连接成功")
        except Exception as err:
            self.flag = False
            print("连接失败", err)

    def close(self):
        self.conn.close()

    def recv(self):
        data = self.conn.recv(1024)
        print(data)

    def send(self, data):
        self.conn.send(data)
        print("发送成功")


if __name__ == '__main__':
    host = "192.168.6.28"
    port = 8000
    ws = WebClient(host, port)
    if not ws.flag:
        ws.connect()
    data = {"device": "bb", "value": "123"}
    data = {"device": "cc", "value": "123"}
    data = json.dumps(data)
    ws.send(data)
相关推荐
Aurora-Borealis.2 分钟前
Day 38 GPU训练和call方法
python
Ulyanov3 分钟前
PyVista三维战场仿真实战
开发语言·python·tkinter·pyvista·gui开发
深蓝电商API3 分钟前
Scrapy爬虫部署到Scrapyd服务端详解
爬虫·python·scrapy
无垠的广袤8 分钟前
【工业树莓派 CM0 NANO 单板计算机】YOLO26 部署方案
linux·python·opencv·yolo·树莓派·目标识别
董世昌418 分钟前
HTTP协议中,GET和POST有什么区别?分别适用什么场景?
java·开发语言·前端
独自破碎E9 分钟前
Java中HashMap的默认负载因子为什么设置为0.75?
java·开发语言·网络
STLearner9 分钟前
AAAI 2026 | 时间序列(Time Series) 论文总结[下] (分类,异常检测,基础模型,表示学习,生成)
大数据·论文阅读·人工智能·python·深度学习·机器学习·数据挖掘
幽络源小助理12 分钟前
SpringBoot+Vue大学城水电管理系统源码 | 后勤设备管理 | 幽络源
java·开发语言
闻林禹13 分钟前
c++并发编程
开发语言·c++
科研鬼才(bushi16 分钟前
项目文件夹规范
python