筱团Blog筱团のBlog

WebSocket

筱团·2022-09-21 16:30·284 次阅读

WebSocket

Prerequisite

背景:我有个微信机器人,源码主体采用的是 WebSocket 库,群友有个需求,就是需要机器人在重要的日期之前提醒,我的方案是让它在重要的日期前一天早上 8 点和晚上 10 点进行提醒。实现过程比较简单,采用多进程(两个就够了),一个负责接收群友的消息并传递对应信息,另一个负责日期提醒

简单来说,WebSocket 是一个持久化的协议(如下图所示),先基于 HTTP 协议建立连接,再进行信息传递,此时信息传递是双向的,即客户端 ⇄ 服务器

参考文章:看完让你彻底搞懂Websocket原理
参考视频:WebSocket打造在线聊天室【第一集】
参考视频:How to Create a WebSocket Server in Python - Fun with WebSockets
参考文章:websocket-client(websocket)和websockets区别

python 库#

python 的 WebSocket 有两个库,分别是 websocket-client 和 websockets。websocket-client 是一个 websocket 服务的 client 端模块,websockets 是一个模块有 server 端和 client 端,一般来前者(websocket-client)是同步的,后者(websockets)是异步的,因此后者常与协程(asyncio)一起用

下载方法分别是 pip install websocket-clientpip install websockets

websocket-client#

我的微信机器人使用的 websocket-client 大致如下:

Copy
#! /usr/bin/env python # -*- coding: UTF-8 -*- import websocket import time websocket._logging._logger.level = -99 ip = '127.0.0.1' port = 5555 SERVER = f'ws://{ip}:{port}' def output(msg): now = time.strftime("%Y-%m-%d %X") print(f'[{now}]:{msg}') def on_open(ws): ws.send("Hello") def on_message(ws, message): print(message) def on_error(ws, error): output(f'on_error:{error}') def on_close(ws): output("closed") if __name__ == '__main__': ws = websocket.WebSocketApp(SERVER, on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close)

此时只有一个进程,用于接收群友的消息并传递对应信息,于是我加了第二个进程后代码如下:

Copy
#! /usr/bin/env python # -*- coding: UTF-8 -*- import websocket import time from multiprocessing import Process websocket._logging._logger.level = -99 ip = '127.0.0.1' port = 5555 SERVER = f'ws://{ip}:{port}' def output(msg): now = time.strftime("%Y-%m-%d %X") print(f'[{now}]:{msg}') def on_open(ws): ws.send("Hello") def on_message(ws, message): print(message) def on_error(ws, error): output(f'on_error:{error}') def on_close(ws): output("closed") def reminder(): pass if __name__ == '__main__': ws = websocket.WebSocketApp(SERVER, on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close) # ws.run_forever() p1 = Process(target=reminder) p2 = Process(target=ws.run_forever) p1.start() p2.start()

相比于之前的代码只是多出了 reminder 函数,且改成了多进程,这样就能同时实现两个功能(reminder 和 run_forever),且互不干扰 ~

websockets#

参考代码:python-websockets(By ParametricCamp)

服务端代码

Copy
#! /usr/bin/env python # -*- coding: UTF-8 -*- import websockets import asyncio PORT = 7890 print("Server listening on Port " + str(PORT)) # 接收 clients,且不重复 connected = set() async def echo(websocket, path): print("A client just connected") # 一个 client 加入 connected.add(websocket) # 处理接收的消息 try: async for message in websocket: print("Received message from client: " + message) # 向发送消息的 client 发送同样的消息 for conn in connected: if conn == websocket: await conn.send("Someone said: " + message) # 处理取消连接的 client except websockets.exceptions.ConnectionClosed as e: print("A client just disconnected") finally: connected.remove(websocket) # 开始工作 start_server = websockets.serve(echo, "localhost", PORT) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever()

客户端代码

Copy
#! /usr/bin/env python # -*- coding: UTF-8 -*- import websockets import asyncio async def listen(): url = "ws://127.0.0.1:7890" # 连接服务器 async with websockets.connect(url) as ws: # 发送消息 await ws.send("Hello Server!") # 等待接收服务端消息 while True: msg = await ws.recv() print(msg) # 开始连接 asyncio.get_event_loop().run_until_complete(listen())

示例图如下:

posted @   筱团  阅读(284)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
历史上的今天:
2021-09-21 汇编前置
点击右上角即可分享
微信分享提示
目录