赞
踩
Websocket协议是对http的改进,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持,直到client或server 中断连接,弥补了http无法保持长连接的不足,方便了客户端应用与服务器之间实时通信。
参考:
由浅入深介绍 Python Websocket 编程-CSDN博客
html单点通信
消息群发
聊天室功能
- import asyncio
- import websockets
- from datetime import datetime
-
- async def handler(websocket):
- data = await websocket.recv()
- reply = f"收到数据:{data} time: {datetime.now()}"
- print(reply)
- await websocket.send(reply)
- print("Send reply")
-
-
- async def main():
- async with websockets.serve(handler, "localhost", 9999):
- await asyncio.Future() # run forever
-
- if __name__ == "__main__":
- asyncio.run(main())
-
-
- import asyncio
- import websockets
- import time
-
- async def ws_client(url):
- for i in range(1, 40):
- async with websockets.connect(url) as websocket:
- await websocket.send("Hello, I'm client 1")
- response = await websocket.recv()
- print(response)
- time.sleep(3)
-
-
- if __name__ == "__main__":
- asyncio.run(ws_client('ws://127.0.0.1:9999'))
- <!DOCTYPE HTML>
- <html>
-
- <head>
- <meta charset="utf-8">
- <title>websocket demo</title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
- <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"> </script>
- <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
- <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
- <script type="text/javascript">
-
- async function wsClient(url) {
- for (let i = 1; i <= 40; i++) {
- const websocket = new WebSocket(url);
-
- // Wait for the WebSocket connection to open
- await new Promise((resolve, reject) => {
- websocket.addEventListener('open', () => {
- resolve();
- });
- websocket.addEventListener('error', reject);
- });
-
- // Send a message to the server
- websocket.send("Hello, I'm client html");
-
- // Wait for a response from the server
- const response = await new Promise((resolve) => {
- websocket.addEventListener('message', (event) => {
- resolve(event.data);
- });
- });
-
- // Print the response
- console.log(response);
-
- // Wait for 3 seconds before sending the next message
- await new Promise(resolve => setTimeout(resolve, 1000));
-
- // Close the WebSocket connection before the next iteration
- websocket.close();
- }
- }
-
- // Call the function with the desired WebSocket URL
- wsClient('ws://127.0.0.1:9999');
- </script>
-
- </head>
-
- <body>
-
- </body>
-
- </html>
python server.py
python client.py
打开client.html
- import asyncio
- import websockets
- from datetime import datetime,time
-
- # 维护一个连接的客户端字典,key为remote_address
- connected_clients = {}
-
- # 处理连接事件
- async def connection_handler(websocket, path):
- remote_address = websocket.remote_address
- print(f"新连接建立 from {remote_address}")
- connected_clients[remote_address] = websocket # 使用remote_address作为key添加到字典中
- print(f"当前连接数:{len(connected_clients)}")
- print(f"连接地址:{list(connected_clients.keys())}")
- try:
- while True:
- await message_handler(websocket)
- except websockets.exceptions.ConnectionClosedOK:
- print(f"连接已正常关闭 from {remote_address}")
- print(f"当前连接地址:{list(connected_clients.keys())}")
- finally:
- del connected_clients[remote_address] # 连接关闭时从字典中移除
-
- # 处理接收到的消息,并广播出去
- async def message_handler(websocket):
- data = await websocket.recv()
- reply = f"收到数据:{data} time: {datetime.now().time()}"
- print(reply)
-
-
- # 广播消息给所有连接的客户端
- for client_websocket in connected_clients.values():
- if client_websocket != websocket: # 避免给自己发送消息
- try:
- await client_websocket.send(reply)
- except websockets.exceptions.ConnectionClosedError:
- # 如果某个客户端连接已经关闭,由于字典的key-value特性,无需显式移除
- print(f"一个连接已关闭,自动从字典中移除")
- print("Broadcast reply sent")
-
- async def main():
- async with websockets.serve(connection_handler, "localhost", 9999):
- await asyncio.Future() # run forever
-
- if __name__ == "__main__":
- asyncio.run(main())
- import asyncio
- import websockets
-
- async def ws_client(url):
- async with websockets.connect(url) as websocket:
- # 发送初始消息
- await websocket.send("Hello, I'm logging.")
-
- # 持续接收消息的循环
- while True:
- try:
- response = await websocket.recv()
- print(f"Received: {response}")
- # 可以根据需要处理接收到的消息,比如判断是否需要发送新的消息等
- except websockets.exceptions.ConnectionClosedError:
- print("Connection closed by server.")
- break # 连接关闭时跳出循环
- except Exception as e:
- print(f"An error occurred: {e}")
- # 根据实际情况决定是否需要重连或进行其他操作
-
- # 可以在这里添加延时以控制发送或接收频率,但需谨慎使用以免阻塞事件循环
- # await asyncio.sleep(1) # 示例:每秒接收一次消息
-
-
- if __name__ == "__main__":
- asyncio.run(ws_client('ws://127.0.0.1:9999'))
- <!DOCTYPE HTML>
- <html>
-
- <head>
- <meta charset="utf-8">
- <title>websocket demo</title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
- <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"> </script>
- <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
- <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
- <script type="text/javascript">
- var ws; // 在更宽的作用域定义WebSocket实例
-
- function WebSocketTest() {
- if ("WebSocket" in window) {
- ws = new WebSocket("ws://127.0.0.1:9999/handler"); // 打开WebSocket连接
-
- ws.onopen = function () {
- ws.send("html login");
- console.log("发送消息(html login)");
- };
-
- ws.onclose = function () {
- console.log("连接已关闭...");
- };
- } else {
- alert("您的浏览器不支持 WebSocket!");
- }
- }
-
- // 新增函数,用于发送消息
- function sendMessage() {
- if (ws && ws.readyState === WebSocket.OPEN) { // 确保WebSocket已连接且处于OPEN状态
- var msgInput = document.getElementById("msgInput"); // 假设有一个输入框用于输入消息
- var msg = msgInput.value || "默认消息内容";
- ws.send(msg);
- console.log("发送消息:" + msg);
- msgInput.value = ""; // 清空输入框
- } else {
- console.warn("WebSocket未连接或非OPEN状态,无法发送消息。");
- }
- }
- </script>
- </head>
-
- <body>
- <div class="col-md-6 m-5 p-2" id="div_ws">
- <a class="btn btn-primary" href="javascript:WebSocketTest()">登录WebSocket</a>
- </div>
- <div class="col-md-6 m-5 p-2" id="div_ws">
- <a class="btn btn-primary" onclick="sendMessage()" >发送消息</a>
- </div>
-
-
- <div class="input-group input-group-lg">
- <div class="input-group-prepend">
- <span class="input-group-text" id="inputGroup-sizing-lg">消息</span>
- </div>
- <input type="text" id="msgInput" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-lg" placeholder="请输入消息内容..." >
- </div>
-
- </body>
-
- </html>
python server.py
python client.py
启动服务端 python server.py
- # reply = f"收到数据:{data} time: {datetime.now().time()}" 修改响应数据
-
- reply = f"{datetime.now().time()} {websocket.remote_address} {data}"
- <!DOCTYPE HTML>
- <html>
-
- <head>
- <meta charset="utf-8">
- <title>websocket demo</title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
- <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"> </script>
- <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
- <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
- <script type="text/javascript">
- var ws; // 在更宽的作用域定义WebSocket实例
-
- function WebSocketTest() {
- if ("WebSocket" in window) {
- ws = new WebSocket("ws://127.0.0.1:9999/handler"); // 打开WebSocket连接
- ws.onopen = function () {
- ws.send("html login");
- console.log("发送消息(html login)");
- };
-
- ws.onmessage = function (event) { // 添加消息接收处理器
- var receivedMsg = document.getElementById("receivedMsg"); // 获取用于显示消息的元素
- receivedMsg.innerHTML += "<br>" + event.data; // 将接收到的消息追加到元素中
- console.log("接收到消息:" + event.data);
- };
-
- ws.onclose = function () {
- console.log("连接已关闭...");
- };
- } else {
- alert("您的浏览器不支持 WebSocket!");
- }
- }
-
- // 新增函数,用于发送消息
- function sendMessage() {
- if (ws && ws.readyState === WebSocket.OPEN) { // 确保WebSocket已连接且处于OPEN状态
- var msgInput = document.getElementById("msgInput"); // 假设有一个输入框用于输入消息
- var msg = msgInput.value || "默认消息内容";
- ws.send(msg);
- console.log("发送消息:" + msg);
- msgInput.value = ""; // 清空输入框
- } else {
- console.warn("WebSocket未连接或非OPEN状态,无法发送消息。");
- }
- }
- </script>
- </head>
-
- <body>
- <div class="col-md-6 m-5 p-2" id="div_ws">
- <a class="btn btn-primary" href="javascript:WebSocketTest()">登录WebSocket</a>
- </div>
- <div class="col-md-6 m-5 p-2" id="div_ws">
- <a class="btn btn-primary" onclick="sendMessage()">发送消息</a>
- </div>
- <div class="input-group input-group-lg">
- <div class="input-group-prepend">
- <span class="input-group-text" id="inputGroup-sizing-lg">消息</span>
- </div>
- <input type="text" id="msgInput" class="form-control" aria-label="Sizing example input"
- aria-describedby="inputGroup-sizing-lg" placeholder="请输入消息内容...">
- </div>
-
- <div class="col-md-12 m-5 p-2" id="receivedMsg" style="height: 200px;overflow-y: scroll;">
- 消息记录区:
- </div>
- </body>
-
- </html>
客户端1,
客户端2,
客户端3,
1,把获取客户端字典做成api
2,打开client.html 请求接口获取客户端字典,相当于获取在线好友列表
3,发送消息,携带通信好友的客户端字典的key值,
4,服务端从客户端字典查找目标连接,并发送消息
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。