websockets 的广播机制
- 老规矩,先上代码再解析
- 这篇主要是学习
websockets
的广播功能 - 可以同时将一个消息发送给多个客户端,保证多个客户端能实时接收到同样的信息
- 只会python不会写html和js也没有关系,代码很简洁,重点是理解
websockets
的广播功能并用python写广播服务器
server端
import asyncio
import datetime
import random
import websockets
Connections = set()
async def broadcast_time():
while True:
message = datetime.datetime.utcnow().isoformat() + "Z"
websockets.broadcast(Connections, message)
await asyncio.sleep(random.random() * 2 + 1)
async def register(websocket):
Connections.add(websocket)
try:
await websocket.wait_closed()
finally:
Connections.remove(websocket)
async def main():
async with websockets.serve(register, "localhost", 5678):
print(f"[server on 5678]")
await broadcast_time()
if __name__ == '__main__':
asyncio.run(main())
html 网页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket demo</title>
</head>
<body>
<script src="show_time.js"></script>
</body>
</html>
js 代码
window.addEventListener("DOMContentLoaded", () => {
const messages = document.createElement("ul");
document.body.appendChild(messages);
const websocket = new WebSocket("ws://localhost:5678/");
websocket.onmessage = ({data}) => {
const message = document.createElement("li");
const content = document.createTextNode(data);
message.appendChild(content);
messages.appendChild(message);
};
});
关键点提示:
- 启动一份server服务器的代码都是一样的,copy即可
- 在这个server中,服务处理函数
register
只有一个作用,就是负责新client 的添加 和离开client的删除 Connections = set()
就是所有在线client的用户集合,广播时的参数就是这个集合- 在
register
中,使用try…finally的目的:确保无论任何情况下client的websocket关闭,都要从Connections集合中删除它 - 此处没有使用
await asyncio.Future()
,而是换成了await broadcast_time()
协程,这个协程需要在server打开时进行,所以放在了服务器利用with
保持开启的期间,并且while True
保证了广播时间功能可以永远运行下去,而不需要asyncio.Future()
,就算把这一行代码下载后面程序也不会运行到它那里去
- 实现效果
- 因为浏览器的打开时间不同,所以只需关注最后三条消息,可以看见他们是一样的
![在这里插入图片描述](https://img-blog.csdnimg.cn/3c448f4ef4514d219b932fa4d5b366b0.png#pic_center)