websocket 单点通信,广播通信

ops/2024/9/24 8:20:52/

        Websocket协议是对http的改进,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持,直到client或server 中断连接,弥补了http无法保持长连接的不足,方便了客户端应用与服务器之间实时通信。

参考:

HTML5 WebSocket | 菜鸟教程

由浅入深介绍 Python Websocket 编程-CSDN博客

应用场景:

        html单点通信

        消息群发

        聊天室功能

一,单点通信

      1,server.py

import asyncio
import websockets
from datetime import datetimeasync 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 foreverif __name__ == "__main__":asyncio.run(main())

        2,python 客户端 client.py

import asyncio
import websockets
import timeasync 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'))

        3,html客户端client.html

<!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 openawait new Promise((resolve, reject) => {websocket.addEventListener('open', () => {resolve();});websocket.addEventListener('error', reject);});// Send a message to the serverwebsocket.send("Hello, I'm client html");// Wait for a response from the serverconst response = await new Promise((resolve) => {websocket.addEventListener('message', (event) => {resolve(event.data);});});// Print the responseconsole.log(response);// Wait for 3 seconds before sending the next messageawait new Promise(resolve => setTimeout(resolve, 1000));// Close the WebSocket connection before the next iterationwebsocket.close();}}                // Call the function with the desired WebSocket URLwsClient('ws://127.0.0.1:9999');</script></head><body></body></html>

        4,启动  :

        python server.py

        python client.py       

         

        打开client.html

二,广播消息

        1,server.py

import asyncio
import websockets
from datetime import datetime,time# 维护一个连接的客户端字典,key为remote_address
connected_clients = {}# 处理连接事件
async def connection_handler(websocket, path):remote_address = websocket.remote_addressprint(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 foreverif __name__ == "__main__":asyncio.run(main())

        2,client.py

import asyncio
import websocketsasync 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'))

        3,html

<!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>

      4,终端启动服务端 

        python server.py

        5,打开多个终端启动多个客户端

                python client.py   

        6,打开html页面,点击登录WebSocket按钮

        7,输入框输入消息,点击发送消息

三,html 聊天室功能

        1,server.py 

        启动服务端 python server.py

    # reply = f"收到数据:{data}  time: {datetime.now().time()}" 修改响应数据reply = f"{datetime.now().time()} {websocket.remote_address} {data}"

      2,  client.html

<!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>

        3,打开3个client.html 客户端,并发送数据

       客户端1,

客户端2,

客户端3,

四,单人聊天功能分析

        1,把获取客户端字典做成api

        2,打开client.html 请求接口获取客户端字典,相当于获取在线好友列表

        3,发送消息,携带通信好友的客户端字典的key值,

        4,服务端从客户端字典查找目标连接,并发送消息


http://www.ppmy.cn/ops/27598.html

相关文章

JAVASE练手项目-ATM

此项目使用到的技术主要是面向对象和JAVA的常用API和ArrayList实现。可以用来做JAVA的基础练手或者是期末作业。 主要功能是&#xff1a;用户开户&#xff0c;登录&#xff0c;存钱&#xff0c;取钱&#xff0c;转账&#xff0c;注销&#xff0c;修改密码。 注&#xff1a;下…

记录 mod_bcg729 编译过程

操作系统: CentOS7.9 FreeSWITCH: 1.10.7&#xff0c;已经源码编译 cd src/mod/codecs/mod_bcg729 git clone https://github.com/xadhoom/mod_bcg729.git cd mod_bcg729 git clone https://github.com/BelledonneCommunications/bcg729.git 修改 ./bcg729/CMakeLists.t…

精通区块链(二)

原文&#xff1a;zh.annas-archive.org/md5/0290aeea847c6aa4c7f7f8ed538e33ef 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;比特币 比特币是区块链技术的第一个应用。在本章中&#xff0c;读者将详细介绍比特币技术。 比特币随着第一个完全去中…

STM32G030F6P6TR 芯片TSSOP20 MCU单片机微控制器芯片

STM32G030F6P6TR 在物联网&#xff08;IoT&#xff09;设备中的典型应用案例包括但不限于以下几个方面&#xff1a; 1. 环境监测系统&#xff1a; 使用传感器来监测温度、湿度、气压等环境因素&#xff0c;并通过无线通信模块将数据发送到中央服务器或云端平台进行分析和监控。…

【问题分析】TaskDisplayArea被隐藏导致的黑屏以及无焦点窗口问题【Android 14】

1 问题描述 用户操作出的偶现的黑屏以及无焦点窗口问题。 直接原因是&#xff0c;TaskDisplayArea被添加了eLayerHidden标志位&#xff0c;导致所有App的窗口不可见&#xff0c;从而出现黑屏和无焦点窗口问题&#xff0c;相关log为&#xff1a; 这个log是MTK添加的&#xff0…

Linux_环境变量

目录 1、查询所有环境变量 2、常见的环境变量 2.1 PATH 2.2 HOME 2.3 PWD 3、增加新的环境变量 4、删除环境变量 5、main函数的三个形参 5.1 argv字符串数组 5.2 env字符串数组 6、系统调用接口 6.1 getenv 6.2 putenv 7、全局变量environ 结语 前言&…

探讨AIGC技术的发展现状和未来趋势

文章目录 每日一句正能量前言技术应用一、AIGC对未来产生了革命性影响二、AIGC将助力元宇宙数字经济的加速发展三、AIGC将加速出版业数字化智能化的转型升级四、AIGC的未来发展趋势及影响 伦理与风险未来展望后记 每日一句正能量 懒人做工作&#xff0c;越懒越费力。 前言 AIG…

通达OA query.php SQL注入漏洞

产品介绍 通达OA&#xff08;Office Automation&#xff09;是一款企业级协同办公软件&#xff0c;旨在为企业提供高效、便捷、安全、可控的办公环境。它涵盖了企业日常办公所需的各项功能&#xff0c;包括人事管理、财务管理、采购管理、销售管理、库存管理、生产管理、办公自…