如何用python快速的搭建一个websocket服务器?

准备工作

python:3.9.x

  • python 依赖
    pip3 install asyncio
    pip3 install json
    pip3 install websockets
    pip3 install pyvisa
    pip3 install configparser

目录结构

-case(功能代码模块文件夹)
--OutputPower.py(功能代码,接收到客户端信息,判断进入对应的功能模块)
-websocket(webSocket服务器代码,主要负责维护连接、接收数据、发送数据)
--server.py(服务器代码)
-app.py(程序入口)

代码

server.py
功能包括:
1、建立websocket连接
2、收取客户端信息
3、发送客户端信息

服务器数据处理模块

此处我使用了多线程,主要是想到以后的功能模块交互问题


import asyncio
import websockets
import time
import json
import threading
# 功能模块
from case.OutputPower import OutputPower

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

class Server():
	# 发消息给客户端的回调函数
    async def s(self,msg,websocket=None):
        await self.sendMsg(msg,websocket)
    # 针对不同的信息进行请求,可以考虑json文本
    async def runCase(self,jsonMsg,websocket):
        print('runCase')
        # await OutputPower(jsonMsg,self.s,websocket)
        op = OutputPower()
        await op.run(jsonMsg,self.s,websocket)

    # 每一个客户端链接上来就会进一个循环
    async def echo(self,websocket, path):
        Clients.append(websocket)
        await websocket.send(json.dumps({"type": "handshake"}))
        while True:
            try:
                recv_text = await websocket.recv()
                message = "I got your message: {}".format(recv_text)
                # 直接返回客户端收到的信息
                await websocket.send(message)
                print(message)

                # 分析当前的消息 json格式,跳进功能模块分析
                await self.runCase(jsonMsg='',websocket=websocket)

            except websockets.ConnectionClosed:
                print("ConnectionClosed...", path)  # 链接断开
                Clients.remove(websocket)
                break
            except websockets.InvalidState:
                print("InvalidState...")  # 无效状态
                Clients.remove(websocket)
                break
            except Exception as e:
                print(e)
                Clients.remove(websocket)
                break

    # 发送消息
    async def sendMsg(self,msg,websocket):
        print('sendMsg:',msg)
        if websocket != None:
            await websocket.send(msg)
        else:
            await self.broadcastMsg(msg)
        # 避免被卡线程
        await asyncio.sleep(0.2)

	# 群发消息
    async def broadcastMsg(self,msg):
        for user in Clients:
            await user.send(msg)

    # 启动服务器
    async def runServer(self):
        async with websockets.serve(self.echo, 'localhost', 8888):
            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()
        print("go!!!")

建立功能模块

做到业务分离(OutputPower.py)

import asyncio

class OutputPower():
    async def run(self,arg,s,websocket):
        # 发送消息方法,单独和请求的客户端发消息
        await s('sssss', websocket)
        # 群发消息
        await s('起来hi')

启动服务

(app.py)


from webSocket.server import Server

if __name__=='__main__':
    s = Server()
    s.startServer()

测试

直接找一个在线的websocket进行连接测试即可,如 http://www.websocket-test.com/

结果如图:

  • 第一个客户端链接
  • 发送:12
  • 服务器返回:I got your message:12
  • 继续返回功能模块的:sssss
  • 返回群发的信息:起来hi
  • 返回群发的信息:起来hi
    如何用python快速的搭建一个websocket服务器?_第1张图片
  • 第二个客户端链接上去
  • 重复第一个客户端工作,但是第一个客户端多接收到了一个:起来hi
    如何用python快速的搭建一个websocket服务器?_第2张图片

怎么解决通信与逻辑分离

于2022.7.13发现一个问题,由于我自己的业务处理时间很长,比如这样的

import asyncio
import time

class OutputPower():
    def __init__(self):
        self._stop = 0

    async def stop(self):
        self._stop = 1
        print('i stop!')

    async def run(self, arg, s, websocket):
        k = 0
        while 1:
            time.sleep(2)
            if self._stop == 1:
                print('i jump out ...')
                break
            print('i am running ...')
            
            k = k+1
            if k== 10:
                break

模拟业务处理:一直要处理20s完成这个业务,但是在开始后发现问题需要立刻停止这个业务,也就是self._stop==1来停止这个业务,如果按照我们上面的设计,收到服务器的消息会就会一直进入 await op.run(jsonMsg,self.s,websocket)业务,直到完成后才会走出这个业务,获得停止的命令,脱离了我们的初衷。
假定我们的协议都是json格式:
开始任务:

{"type": 1}

结束任务

{"type": 2}

那么在页面上的交互逻辑,我直接截图来表达下流程:
如何用python快速的搭建一个websocket服务器?_第3张图片
步骤如下:
1、websocket建立连接,返回{\type\: \handshake\}
2、开始执行任务,下发:{"type": 1}
3、任务开始执行,返回正在执行的进度:i am running ... 0
4、任务没完成的时候,下发中止任务:{"type": 2}
5、任务中止,输出:stop!

其实这个做法有很多,我在这里就简单的说下我自己的原理:
1、websocket接收数据,缓存到全局变量queue中;
2、server处理增加线程读取这个queue,取出交互协议;
3、再次启动threading去处理该协议内容。

具体的代码可以见下方的测试代码。

测试源码

见:https://download.csdn.net/download/weixin_44635546/85645105

你可能感兴趣的:(python,websocket,python,服务器)