websocket 单点通信,广播通信

        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.mzph.cn/bicheng/4621.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据005-hadoop003-了解MR及Java的简单实现

了解MapReduce MapReduce过程分为两个阶段&#xff1a;map阶段、reduce阶段。每个阶段搜键-值对作为输入和输出。 要执行一个MR任务&#xff0c;需要完成map、reduce函数的代码开发。 Hellow World 【Hadoop权威指南】中的以分析气象数据为例&#xff0c;找到每年的最高气温。…

Jenkins持续化集成

优质博文&#xff1a;IT-BLOG-CN 工作过程如下环境准备 开发人员提交代码>jenkins获取代码>调用单元测试>打包>发布 环境准备Jenkins的安装 Tomcat、Maven、Git或Svn、Jdk Jenkins的安装 1、官网下载war &#xff1a;http://Jenkins-ci.org/ 2、tomcat-users.…

NTFS文件权限管理

实验环境 windows server 2016 实验要求 实验步骤 1、 新建文件 2、打开文件夹的属性->安全->高级 3、禁用继承 4、添加组或用户 技术资料&#xff1a; 常用软件&#xff1a; 手机端项目&#xff1a; 电脑端项目&#xff1a; 公司制度&#xff1a; 销售资源&#xff…

【Scala---01】Scala『 Scala简介 | 函数式编程简介 | Scala VS Java | 安装与部署』

文章目录 1. Scala简介2. 函数式编程简介3. Scala VS Java4. 安装与部署 1. Scala简介 Scala是由于Spark的流行而兴起的。Scala是高级语言&#xff0c;Scala底层使用的是Java&#xff0c;可以看做是对Java的进一步封装&#xff0c;更加简洁&#xff0c;代码量是Java的一半。 因…

JAVA读取从WPS在Excel中嵌入的图片资源

读取从WPS在Excel中嵌入的图片资源 引言 许多数据文件中可能包含嵌入式图片&#xff0c;这些图片对于数据分析和可视化非常重要。然而&#xff0c;从 WPS 在 Excel 中读取这些图片可能会有一些技术挑战。在本文中&#xff0c;我将展示如何从 WPS Excel 文件中读取嵌入的图片&am…

海外三大AI图片生成器对比(Stable Diffusion、Midjourney、DALL·E 3)

Stable Diffusion DreamStudio 是Stable Diffusion 的官方网页&#xff0c;价格便宜&#xff0c;对图片的操作性强&#xff0c;但同时编辑页面不太直观&#xff0c;对使用者的要求较高。 与 DALLE 和 Midjourney 不同&#xff0c;Stable Diffusion 是开源的。这也意味着&…

linux tcpdump的交叉编译以及使用

一、源码下载 官网&#xff1a;点击跳转 二、编译 1、解压 tar -xf libpcap-1.10.4.tar.xz tar -xf tcpdump-4.99.4.tar.xz 2、配置及编译 //libpcap&#xff1a; ./configure --hostarm-linux --targetarm-linux CCarm-linux-gcc --with-pcaplinux --prefix$PWD/build//t…

企业如何保证内部传输文件使用的工具是安全的?

企业内部文件的频繁交换成为了日常运营不可或缺的一环。然而&#xff0c;随着数据量的爆炸式增长和网络攻击手段的日益复杂&#xff0c;内网文件传输的安全隐患也日益凸显&#xff0c;成为企业信息安全的薄弱环节。本文将探讨内网文件传输的安全风险、企业常用的防护措施。 内网…

Django之搭配内网穿透

一&#xff0c;安装coplar 二&#xff0c;开启8087的内网穿透 三&#xff0c;setting.py中加入如下配置&#xff1a; ALLOWED_HOSTS [*]CSRF_TRUSTED_ORIGINS ["https://localhost:8087", "http://localhost:8087"]四&#xff0c;启动项目 五&#xff…

STM32之HAL开发——ADC入门介绍

ADC简介 模数转换&#xff0c;即Analog-to-Digital Converter&#xff0c;常称ADC&#xff0c;是指将连续变量的模拟信号转换为离散的数字信号的器件&#xff0c;比如将模温度感器产生的电信号转为控制芯片能处理的数字信号0101&#xff0c;这样ADC就建立了模拟世界的传感器和…

第4篇:创建Nios II工程之Hello_World<三>

Q&#xff1a;接着我们再来完成Nios II软件工程设计部分。 A&#xff1a;从Quartus Tools选择Nios II Software Build Tools for Eclipse&#xff0c;打开Nios II SBT软件&#xff0c;Workspace指定到hello_world工程的software文件夹路径&#xff1b;再从File-->New-->…

Linux命令大全 以及搭建hadoop

Liunx系统目录 ├── bin -> usr/bin # 用于存放二进制命令 ├── boot # 内核及引导系统程序所在的目录 ├── dev # 所有设备文件的目录&#xff08;如磁盘、光驱等&#xff09; ├── etc # 配置文件默认路径、服务启动命令存放目录 ├── home # 用户家目录&#…

上位机图像处理和嵌入式模块部署(树莓派4b设置ftp下载)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 作为一个开发板&#xff0c;最好支持ftp下载&#xff0c;这样文件的上传和下载都会比较方便。虽然目前为止&#xff0c;利用mobaxterm和ssh也能实现…

ObjectARX特性面板OPM添加动态属性

参考资料 AutoCAD与动态属性PDF文档 https://www.progdomain.com/584/ObjectARX2016 OPM面板全攻略 https://blog.csdn.net/jfmyes/article/details/121392332 准备工作——正确安装ARX和Wizards ARX和VS的版本对应、ObjectArx(2010~2020)工程创建、类添加及错误处理 https:…

《从Paxos到Zookeeper》——第四、七章:基本概念及原理

目录 第四章 Zookeeper与Paxos 4.1 Zk是什么 4.1.1 Zk特性 4.1.2 Zk基本概念 4.1.2.1 集群角色(Follower, Leader, Observer) 4.1.2.2 数据模型 4.1.2.3 ZNode(数据节点) 4.1.2.4 Session(会话) 4.1.2.5 ACL&#xff08;Access Control Lists&#xff09; 4.1.2.6 Watcher(事件…

如何用OceanBase的 Load Data 导入CSV文件

0 前言 CSV文件&#xff08;Comma-Separated Values&#xff0c;字符分隔值&#xff09;是一种普遍采用的数据存储格式&#xff0c;有不少企业和机构都用它来进行数据的管理和存储。身为开发者&#xff0c;您可能经常遇到这样的需求&#xff1a;需要将CSV的数据导入OceanBase数…

OpenCV如何实现背投

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV直方图比较 下一篇 :OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 目标 在本教程中&#xff0c;您将学习&#xff1a; 什么是背投以及它为什么有用如何使用 Ope…

stm32单片机开发二、定时器-内部时钟中断和外部时钟中断、编码器

定时器本质就是一个计数器 案例&#xff1a;定时器定时中断 内部时钟中断 Timer_Init(); //定时中断初始化 /*** 函 数&#xff1a;定时中断初始化* 参 数&#xff1a;无* 返 回 值&#xff1a;无*/ void Timer_Init(void) {/*开启时钟*/RCC_APB1PeriphClockCmd(RCC…

纯血鸿蒙APP实战开发——Navigation实现多设备适配案例

介绍 在应用开发时&#xff0c;一个应用需要适配多终端的设备&#xff0c;使用Navigation的mode属性来实现一套代码&#xff0c;多终端适配。 效果图预览 使用说明 将程序运行在折叠屏手机或者平板上观看适配效果。 实现思路 本例涉及的关键特性和实现方案如下&#xff1a…

HTML5(2)

目录 一.列表、表格、表单 1.列表标签 2.表格 4.无语义的布局标签 5.字符实体 6.综合案例--1 7.综合案例--表单 一.列表、表格、表单 1.列表标签 1.1 无序列表 1.2 有序列表 1.3 定义列表 定义列表一般用于网页底部的帮助中心 2.表格 2.1 2.2 表格结构标签 shiftaltf 格…