用Python做一个websocket服务端

news2024/11/23 11:23:33

我对websocket服务端的功能定义是:

1.能将client端的软硬件信息关联(如client_name和对应ip:port),且不支持重复关联;

2.可以判断接收自client端的消息属于哪种任务,并对应执行(如关联、发消息);

3.根据接收自client端的消息判断是点对点发送,还是广播发送,并执行。

参考其他大神们写的代码,我用python实现了上述功能需求:

import asyncio
import websockets
import json
import threading

# 存储所有的客户端
Clients = []

# 服务端
class WS_Server():
    def __init__(self):
        self.ip = "127.0.0.1"
        self.port = 9090

    # 发送消息
    async def sendMsg(self, websocket, msg):
        if websocket != None:
           await websocket.send(msg)
        else:
            self.broadcast(msg)
        await asyncio.sleep(0.2)


    # 群发消息
    async def broadcast(self, msg):
        for user in Clients:
           await user['socket'].send(msg)


    # 连接一个客户端,起一个循环监听
    async def echo(self, websocket):
        # 握手
        client_ip, client_port = websocket.remote_address
        print(f"连接到:{client_ip}:{client_port}")
        await websocket.send(json.dumps({"stat": "success"}))
        # 循环监听
        while True:
            try:
                recv_text = await websocket.recv()
                message = "收到消息: {}".format(recv_text)
                await websocket.send(message)
                data = json.loads(recv_text)
                receiver = data['to']
                content = data['content']
                sender = data['from']
                stat = data['stat']
                if stat == "link":
                    checked = False
                    if len(Clients) > 0 :
                        for usr in Clients:
                            if usr['name'] == sender:
                                checked = True
                                break
                        if checked:
                            print(f"{client_ip}:{client_port}不能被重复关联")
                        else:
                            Clients.append({"socket": websocket, "name": sender})
                            print(f"{sender} 已关联 {client_ip}:{client_port}")
                    else:
                        Clients.append({"socket": websocket, "name": sender})
                        print(f"{sender} 已关联 {client_ip}:{client_port}")
                else:
                    msg = json.dumps({"stat": stat, "to": receiver, "content": content, "from": sender})
                    if receiver == "":
                        await self.broadcast(msg)
                        print('消息已群发')
                    else:
                        checked1 = False
                        for usr in Clients:
                            if usr['name'] == receiver:
                                socket = usr['socket']
                                await self.sendMsg(socket, msg)
                                checked1 = True
                                break
                        if checked1:
                            print(f"已给{receiver}发送消息")
                        else:
                            print(f"发送失败,未找到{receiver}")

            except websockets.ConnectionClosed:
                print(f"从{client_ip}:{client_port}断开连接")
                break
            except websockets.InvalidState:
                print("无效状态")
                break
            except Exception as e:
                print("ws连接报错", e)
                break

    # 启动服务器
    async def runServer(self):
        async with websockets.serve(self.echo, self.ip, self.port):
            await asyncio.Future()  # run forever

	# 多协程模式,防止阻塞主线程无法做其他事情
    def WebSocketServer(self):
        asyncio.run(self.runServer())

    # 多线程启动
    def startServer(self):
        # 多线程启动,否则会堵塞
        thread = threading.Thread(target=self.WebSocketServer)
        thread.start()
        # thread.join()


if __name__=='__main__':
    s = WS_Server()
    s.startServer()
    print("ws服务已启动")

启动WS服务后,客户端需要按照如下数据格式发消息:

{"stat":"","to": "", "content": "", "from":""}

其中,stat包括link和send两种状态,to是消息接者者(receiver),from是消息发送者(sender)。若to为空,则表示该消息是广播消息;若to不为空,但对象不存在,则该消息不会被执行发送。

最后,附上我参考的两篇CSDN文章:

Python中websockets服务端从客户端接收消息并发送给多线程_python websocket 多线程-CSDN博客

python的websocket方法教程_python websocket-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2245957.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

51c大模型~合集76

我自己的原文哦~ https://blog.51cto.com/whaosoft/12617524 #诺奖得主哈萨比斯新作登Nature,AlphaQubit解码出更可靠量子计算机 谷歌「Alpha」家族又壮大了,这次瞄准了量子计算领域。 今天凌晨,新晋诺贝尔化学奖得主、DeepMind 创始人哈萨…

深入了解 Linux htop 命令:功能、用法与示例

文章目录 深入了解 Linux htop 命令:功能、用法与示例什么是 htop?htop 的安装htop的基本功能A区:系统资源使用情况B区:系统概览信息C区:进程列表D区:功能键快捷方式 与 top 的对比常见用法与示例实际场景应…

XML文件(超详细):XML文件概念、作用、写法、如何用程序解析XML、写入XML、dom4j框架、DTD文档、schema文档

目录 1、什么是XML文件?和properties属性文件有什么区别?和txt文本文件有什么区别? 2、XML文件的用途 3、XML的格式 4、如何解析XML文件 5、如何写入XML文件 6、约束XML的书写格式 6.1 DTD文档-约束书写格式,但是不能约束具…

通过端口测试验证网络安全策略

基于网络安全需求,项目中的主机间可能会有不同的网络安全策略,这当然是好的,但很多时候,在解决网络安全问题的时候,同时引入了新的问题,如k8s集群必须在主机间开放udp端口,否则集群不能正常的运…

国产光耦合器的竞争优势与市场发展前景

国产光耦合器近年来在技术研发和市场表现上取得了显著进步,逐渐在国际市场中占据了一席之地。作为实现电气隔离和信号传输的核心器件,光耦合器在工业控制、通信设备、消费电子等领域中有着广泛的应用。国产光耦合器凭借其独特的成本、技术和市场优势&…

Wi-Fi 8标准已经发布,准备好了吗

今年初,Wi-Fi联盟宣布完成并推出了Wi-Fi 7高级无线标准的认证,将改善家庭、办公室和工业用途设备的连接性能,同时还带来了新的认证标志。其在Wi-Fi 6E的基础上引入了320MHz信道带宽、4096-QAM调制、Multi-RU、多链路操作、增强MU-MIMO、多AP协…

STM32F407ZGT6驱动TCA9535扩展16路IO

目录 一、TCA9535 I/O 扩展器1、TCA9535 的 I2C 地址2、TCA9535 的读写操作3、TCA9535 的控制寄存器4、输入寄存器 0/15、输出寄存器 0/16、极性反转寄存器 0/17、配置寄存器 0/1 二、硬件设计1、接线说明2、硬件参考 三、程序设计1、tca9535_softiic.c2、tca9535_softiic.h3、…

一分钟学习数据安全——数据安全风险的系统化应对思路

数据是组织的重要资产,未经授权的数据访问可能导致数据泄露、数据篡改、隐私侵犯和合规风险等问题。企业可以通过数据访问控制来提高信息系统在数据全生命周期管理中的安全性。企业可以引入IAM系统,来控制身份来管理权限。通过对用户访问权限的管理和合适…

空间计算、物理计算、实时仿真与创造拥有「自主行为」的小狗 | 播客《编码人声》

「编码人声」是由「RTE开发者社区」策划的一档播客节目,关注行业发展变革、开发者职涯发展、技术突破以及创业创新,由开发者来分享开发者眼中的工作与生活。 虚拟世界与现实世界的界限逐渐模糊,已然成为不争的事实。但究竟哪些曾经的幻想已然…

shell脚本(三)

声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…

一次封装,解放双手:Requests如何实现0入侵请求与响应的智能加解密

引言 之前写了 Requests 自动重试的文章,突然想到,之前还用到过 Requests 自动加解密请求的逻辑,分享一下。之前在做逆向的时候,发现一般医院的小程序请求会这么玩,请求数据可能加密也可能不加密,但是返回…

基于Springboot+Vue的救灾物资调动系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

『 Linux 』网络层 - IP协议(一)

文章目录 IP协议报文格式IP协议报文如何进行报头与有效载荷分离 网段划分CIDR特殊的IP地址 IP地址的数量限制私有IP和公网IP理解运营商 IP协议报文格式 IP协议报文格式与TCP协议的报文格式类似; IP报文的宽度也是32位; 对应的IP的实际报头为20字节为定长报头(固定长度); 版本 …

[cg] vulkan external_memory

最近在写硬件编码的代码,渲染器渲染出的RT需要给到编码器做硬编,有两种方法能做。 一是通过 map的方式,把显存里的数据读到cpu,拷贝一份cpu data给编码器,但这种方式会有内存拷贝的开销。所以,我们思考是否…

springboot课程答疑系统(代码+数据库+LW)

摘要 随着信息互联网信息的飞速发展,无纸化作业变成了一种趋势,针对这个问题开发一个专门适应师生交流形式的网站。本文介绍了课程答疑系统的开发全过程。通过分析企业对于课程答疑系统的需求,创建了一个计算机管理课程答疑系统的方案。文章…

# issue 4 进程控制函数

目录 一、进程控制函数一 二、进程控制函数二 启动进程:(exec系列) 创建新进程: 测试代码: 测试结果: 三、进程控制函数三 结束进程: 测试代码: 测试结果: 四、…

Linux|进程程序替换

目录 什么是进程替换 替换原理 exec函数 exec* 函数的共性 什么是进程替换 进程程序替换是指将一个进程中正在运行的程序替换为另一个全新的程序的过程,但替换不是创建新进程,只是将对应程序的代码和数据进行替换。具体来说,这个替换过程涉…

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略(详细解题思路)

在当下, 日益发展的时代,宠物的数量应该均为稳步上升,在美国出现了下降的趋势, 中国 2019-2020 年也下降,这部分变化可能与疫情相关。需要对该部分进行必要的解释说明。 问题 1: 基于附件 1 中的数据及您的团队收集的…

人工智能(AI)与机器学习(ML)基础知识

目录 1. 人工智能与机器学习的核心概念 什么是人工智能(AI)? 什么是机器学习(ML)? 什么是深度学习(DL)? 2. 机器学习的三大类型 (1)监督式学…

【从零开始的LeetCode-算法】3233. 统计不是特殊数字的数字数量

给你两个 正整数 l 和 r。对于任何数字 x,x 的所有正因数(除了 x 本身)被称为 x 的 真因数。 如果一个数字恰好仅有两个 真因数,则称该数字为 特殊数字。例如: 数字 4 是 特殊数字,因为它的真因数为 1 和…