当前位置: 首页 > news >正文

第五节:使用SMB开发WebSocket通信

一、概述

本节主要讲解在SMB中如何进行websocket快速开发,实现客户端连接、关闭、消息通讯等功能。

示例下载:https://download.csdn.net/download/lllllllllluoyi/88949743

二、创建WebSocket服务器

1、在csdnProject工程中新建一个消息流。

添加WebSocket Server和四个Java计算节点组件,具体流程如图:

2、各组件说明

WebSocket1:websocket服务器组件,端口设置8100;

route:主要作用是路由。因为WebSocket1会产生open、close、onMessage动作,需要在这里进行逻辑分流,具体代码是:

package sashulin.apps;
import sashulin.Models.MessageModel;
import sashulin.applications.FlowApi;
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.*;public class csdn_websocketServer_route {private String routeLabels = "";public String execute(MessageModel messageModel,String message){String eventName = messageModel.eventName;switch(eventName){case "open":routeLabels = "openWebSocket";break;case "close":routeLabels = "closeWebSocket";break;default:routeLabels = "processWebSocket";break;}return message;}public String getRouteLabels(){return routeLabels;}}

openWebSocket:客户端连接服务器的处理逻辑。

package sashulin.apps;
import sashulin.Models.MessageModel;
import sashulin.applications.FlowApi;
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.*;
import sashulin.websocket.SashulinWebSocket;
public class csdn_websocketServer_openWebSocket {private String routeLabels = "";public String execute(MessageModel messageModel,String message){System.out.println("已连接webSocket服务器,参数信息:"+message);//在内存中保存IP对应的websocket对象SashulinWebSocket webSocket = (SashulinWebSocket)messageModel.object;JSONObject msgJson = new JSONObject(message);String ip = msgJson.getString("clientIP");if (!webSocket.clients.containsKey(ip)){webSocket.clients.put(ip, messageModel.object2);}return "ok";}public String getRouteLabels(){return routeLabels;}
}

closeWebSocket:客户端关闭的逻辑处理。

package sashulin.apps;
import sashulin.Models.MessageModel;
import sashulin.applications.FlowApi;
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.*;
import sashulin.websocket.SashulinWebSocket;
public class csdn_websocketServer_closeWebSocket {private String routeLabels = "";public String execute(MessageModel messageModel,String message){System.out.println("已断开与webSocket服务器的连接,参数信息:"+message);SashulinWebSocket webSocket = (SashulinWebSocket)messageModel.object;String ip = message;if (webSocket.clients.containsKey(ip)){webSocket.clients.remove(ip);}return "ok";}public String getRouteLabels(){return routeLabels;}}

processWebSocket:消息收到后的处理逻辑。

package sashulin.apps;
import sashulin.Models.MessageModel;
import sashulin.applications.FlowApi;
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.*;
public class csdn_websocketServer_processWebSocket {private String routeLabels = "";public String execute(MessageModel messageModel,String message){System.out.println("收到消息:"+message);return "ok";}public String getRouteLabels(){return routeLabels;}}

三、JavaScript向websocket发送消息

通过JavaScript中向websocket服务器连接,发送消息、关闭动作。本例示使用HtmlVCL前端框架进行开发,也可以自己写测试界面代码。界面效果如图:

本示例中包含了两个文件:index.html和websocket.html。

index.html代码
 

<meta charset="utf-8"> <link rel="stylesheet" href="css/vcl.css"><script type="text/javascript" src="js/vcl.js"></script><script type="text/javascript">function main() {var form = new HtmlForm(null);form.align = "center";form.color = "blue";form.Refresh();var popupMenu1 = new HtmlPopupMenu(form);popupMenu1.items = [{id:1,text:"copy"},{id:2,text:"paste"},{id:-1,text:"-"},{id:3,text:"cut"}];popupMenu1.onclick = function(obj,evt){alert(obj.text);alert(evt.id);alert(evt.text);}var topPanel = new HtmlPanel(form);topPanel.align = "top";topPanel.alignment = "center";topPanel.color = "#333";topPanel.fontSize = 14;topPanel.fontColor = "White";topPanel.name="topPanel1";//topPanel.text = "<h1>ChromeWebBrowser.net User Guide</h1>";topPanel.Refresh();var logoPanel = new HtmlPanel(topPanel);logoPanel.align = "left";logoPanel.width = 200;logoPanel.Refresh();var logoImg = new HtmlImage(logoPanel);logoImg.imageUrl = "img/sashulin.png";logoImg.left = 18;logoImg.top = 15;logoImg.width = 32;logoImg.height = 32;logoImg.Refresh();var top_right_panel = new HtmlPanel(topPanel);top_right_panel.align = "right";top_right_panel.width = 200;top_right_panel.Refresh();var userImg = new HtmlImage(top_right_panel);userImg.imageUrl = "img/p.png";userImg.left = 10;userImg.top = 20;userImg.width = 20;userImg.height = 20;userImg.Refresh();var userLabel = new HtmlLabel(top_right_panel);userLabel.alignment = "left";userLabel.left = 40;userLabel.top = 23;userLabel.width = "auto";userLabel.height = 25;userLabel.text = "Hi,Roy";userLabel.fontColor = "white";userLabel.fontSize = 14;userLabel.Refresh();var quitButton = new HtmlLinkButton(top_right_panel);quitButton.top = 20;quitButton.left = 120;quitButton.width = "auto";quitButton.height = 25;quitButton.text = "退出";quitButton.fontColor = "white";quitButton.fontSize = 14;quitButton.setUrl("index.html");quitButton.Refresh();var top_center_panel = new HtmlPanel(topPanel);top_center_panel.align = "center";top_center_panel.Refresh();var popupMenu2 = new HtmlPopupMenu(form);popupMenu2.items = [{id:1,text:"白血病"},{id:2,text:"肺炎"},{id:-1,text:"-"},{id:3,text:"流感"}];popupMenu2.onclick = function(obj,evt){alert(obj.text);alert(evt.id);alert(evt.text);}var titleLabel = new HtmlLabel(logoPanel);titleLabel.alignment = "left";titleLabel.left = 60;titleLabel.top = 20;titleLabel.width = 300;titleLabel.height = 25;titleLabel.text = "Sashulin Message Broker示例";titleLabel.fontColor = "#00ffe2";titleLabel.fontSize = 16;titleLabel.Refresh();var leftPanel = new HtmlPanel(form);leftPanel.name = "leftPanel1";leftPanel.align = "left";leftPanel.color = "#e6e6e6";leftPanel.width = "200";leftPanel.Refresh();var frame = new HtmlFrame(form);frame.align = "center";frame.color = "White";// frame.setUrl("pages/method-EN.html");frame.setUrl("pages/tabs.html");frame.Refresh();var bottomPanel = new HtmlPanel(form);bottomPanel.align = "bottom";bottomPanel.alignment = "center";bottomPanel.color = "#000";bottomPanel.height = 25;bottomPanel.fontColor = "White";bottomPanel.text = "@Author: Roy (173783000@qq.com)";bottomPanel.Refresh();var navBar = new HtmlNavBar(leftPanel);navBar.name = "navBar1";navBar.align = "center";navBar.width = "200";navBar.alignment = "center";navBar.color = "#393D49";navBar.items = [{"title":"WebSocket","items":[{"id":"1","caption":"WebSocket","img":"img/p.png"}]}];navBar.onGroupItemClick = function(event){//alert(event.control.id+":"+event.control.text); var url = "";switch(event.control.id){case "1":url = "pages/websocket.html";break;default:url = "pages/method-EN.html";break;}frame.setUrl(url);}navBar.Refresh();}</script>

websocket.html代码

<!DOCTYPE html>
<script type="text/javascript" src="../js/vcl.js"></script>
<script type="text/javascript">function main() {var websocket;var form = new HtmlForm(null);form.align = "center";form.color = "#eee";form.Refresh();//第一排var button1 = new HtmlButton(form);button1.left = 380;button1.top = 50;button1.width = 100;button1.height = 30;button1.text = "连接"button1.onclick = function () {websocket = new WebSocket(edit1.text);websocket.onerror = (event)=>{  label_status.setText("WebSocket连接发生错误");};//连接成功建立的回调方法  websocket.onopen = (event) => {  label_status.setText("已连接");}  //接收到消息的回调方法  websocket.onmessage = (event) => {  edit_content.setText(event.data);}  //连接关闭的回调方法  websocket.onclose = (event) => {  label_status.setText("已关闭");}}button1.Refresh();var closeButton = new HtmlButton(form);closeButton.left = 500;closeButton.top = 50;closeButton.width = 100;closeButton.height = 30;closeButton.text = "关闭"closeButton.onclick = function () {	websocket.close();}closeButton.Refresh();var label_status = new HtmlLabel(form);label_status.text = "--";label_status.left = 100;label_status.top = 20;label_status.Refresh();var label1 = new HtmlLabel(form);label1.text = "服务器";label1.left = 100;label1.top = 50;label1.Refresh();var edit1 = new HtmlEdit(form);edit1.text = "ws://127.0.0.1:8100";edit1.left = 160;edit1.top = 50;edit1.width = 200;edit1.Refresh();//第二排var button2 = new HtmlButton(form);button2.left = 380;button2.top = 100;button2.width = 100;button2.height = 30;button2.text = "发送"button2.onclick = function () {}button2.Refresh();var label2 = new HtmlLabel(form);label2.text = "发送内容";label2.left = 100;label2.top = 100;label2.Refresh();var edit2 = new HtmlEdit(form);edit2.text = "测试消息";edit2.left = 160;edit2.top = 100;edit2.width = 200;edit2.Refresh();var label3 = new HtmlLabel(form);label3.text = "收到内容";label3.left = 100;label3.top = 150;label3.Refresh();var edit_content = new HtmlEdit(form);edit_content.text = "";edit_content.left = 160;edit_content.top = 150;edit_content.width = 200;edit_content.Refresh();}</script>

运行的效果:

四、两个客户端通讯

在真实场景中是进行消息推送。我们在csdnProject工程进行以下先改:

1、增加一个api接口

这个消息流的逻辑是:开放一个api接口,用户调用接口后向服务器发送websocket消息。在action组件中进行对websocketClient组件的操控,代码如:

package sashulin.apps;
import sashulin.Models.MessageModel;
import sashulin.applications.FlowApi;
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.*;
public class csdn_HttpFlow_action {private String routeLabels = "";public String execute(MessageModel messageModel,String message){JSONObject json = new JSONObject(message);String action = json.getString("action");String text = json.getString("text");switch(action){case "send":FlowApi.execute(this,"WebSocketClient1","send",message);break;case "close":FlowApi.execute(this,"WebSocketClient1","close",text);break;}return "ok";}public String getRouteLabels(){return routeLabels;}}

FlowApi.execute(this,"WebSocketClient1","send",message); //执行websocketClient的Send操作。

FlowApi.execute(this,"WebSocketClient1","close",text); //执行websocketClient的Close操作。

2、修改processWebSocket组件代码

修改服务器的消息接收后的逻辑处理。即向指定的客户发送消息:

package sashulin.apps;
import sashulin.Models.MessageModel;
import sashulin.applications.FlowApi;
import org.json.JSONArray;
import org.json.JSONObject;
import java.sql.*;
import sashulin.websocket.SashulinWebSocket;
import org.java_websocket.WebSocket;
public class csdn_websocketServer_processWebSocket {private String routeLabels = "";public String execute(MessageModel messageModel,String message){System.out.println("收到消息:"+message);JSONObject json = new JSONObject(message);String destIP = json.getString("destIP");String text = json.getString("text");SashulinWebSocket webSocket = (SashulinWebSocket)messageModel.object;if (webSocket.clients.containsKey(destIP)){Object obj = webSocket.clients.get(destIP);WebSocket conn = (WebSocket)obj;conn.send(text);}return "ok";}public String getRouteLabels(){return routeLabels;}}

3、测试消息发送

首先在SashulinMessageBroker示例中连接服务器;

然后再PostMan中发送消息:

SMB示例中收到来自于postman的消息:

结束语:应用于生产环境中会更复杂,但核心点还是在ProcessMessage组件这里,把消息推送何处?推送几次?这些可以做成策略。目前我们全院消息通讯平台也是按这个逻辑进行开发,在国内西南某大型儿童医院为例,进行了2000个客户端,20几个系统的消息对接和众多业务场景设计,稳定、准确运行。

相关文章:

第五节:使用SMB开发WebSocket通信

一、概述 本节主要讲解在SMB中如何进行websocket快速开发&#xff0c;实现客户端连接、关闭、消息通讯等功能。 示例下载&#xff1a;https://download.csdn.net/download/lllllllllluoyi/88949743 二、创建WebSocket服务器 1、在csdnProject工程中新建一个消息流。 添加W…...

Nginx和Ribbon实现负载均衡的区别

Nginx和Ribbon的区别 1. Nginx服务器端负载均衡&#xff1a; 1、Nginx是客户端所有请求统一交给nginx&#xff0c;由nginx进行实现负载均衡请求转发&#xff0c;属于服务器端负载均衡。即请求有nginx服务器端进行转发。 3、Nginx是服务端的负载均衡&#xff0c;Ribbon是客户端…...

流畅的Python(十九)-动态属性和特性

一、核心要义 在Python中,数据的属性和处理数据的方法,统称属性。方法&#xff0c;只是可调用的属性。除了这两者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法(即读值方法和设值方法)修改数据属性。 二、代码示例 0、相关知识点 #!/usr/bin/env…...

确保云原生部署中的网络安全

数字环境正在以惊人的速度发展&#xff0c;组织正在迅速采用云原生部署和现代化使用微服务和容器构建的应用程序&#xff08;通常运行在 Kubernetes 等平台上&#xff09;&#xff0c;以推动增长。 无论我们谈论可扩展性、效率还是灵活性&#xff0c;对于努力提供无与伦比的用…...

【分布式websocket 】前端vuex管理客户端消息crud!使用localStorage来存储【第19期】

前言 聊天系统客户端是要存储消息的&#xff0c;因为所有所有的历史消息都从服务器拉的话一方面服务器压力大&#xff0c;另一方面也耗费用户流量。所以客户端存储消息是势在必行的。如何存储呢上一篇文章也写了&#xff0c;大概就是浏览器的话是localStorage或者IndexedDB。然…...

venv uvicorn python 虚拟服务器外网无法访问

python -m venv .venv source ./.venv/bin/activate pip install -r requirements.txt ./run.sh source ./.venv/bin/activate uvicorn main:app --reload 虚拟web服务器外网访问控制台启动命令用以下代码启动 uvicorn main:app --host 0.0.0.0 --port 8501 --reload 启动到后…...

一款博客网站源码

一款博客网站源码 源码软件库 为大家内置了主题 清爽又强大真正的永久可用的一条源码&#xff0c;该版本为整合版本&#xff0c;内置了Joe主题&#xff0c;搭建后直接启用即可~ 安装环境要求&#xff1a; PHP 7.2 以上 MySQL, PostgreSQL, SQLite 任意一种数据库支持&#xff…...

Mr-Robot1靶场练习靶场推荐小白入门练习靶场渗透靶场bp爆破wordpress

下载链接&#xff1a; Mr-Robot: 1 ~ VulnHub 安装&#xff1a; 打开vxbox&#xff0c;菜单栏----管理----导入虚拟电脑 选择下载完的ova文件&#xff0c;并修改想要保存的位置&#xff08;也可以保持默认位置&#xff09; 导入完成后可以根据自己的情况去配置网络链接方式 完成…...

数据仓库的设计开发应用(三)

目录 五、数据仓库的实施&#xff08;一&#xff09;数据仓库的创建&#xff08;二&#xff09;数据抽取转换加载 六、数据仓库系统的开发&#xff08;一&#xff09;开发任务&#xff08;二&#xff09;开发方法&#xff08;三&#xff09;系统测试 七、数据仓库系统的应用&am…...

【04】WebAPI

WebAPI 和标准库不同,WebAPI 是浏览器提供的一套 API,用于操作浏览器窗口和界面 WebAPI 中包含两个部分: BOM:Browser Object Model,浏览器模型,提供和浏览器相关的操作DOM:Document Object Model,文档模型,提供和页面相关的操作BOM BOM 提供了一系列的对象和函数,…...

数据预处理在数据挖掘中的重要性

数据挖掘作为从大量数据中提取有用信息和知识的过程&#xff0c;其结果的准确性和可靠性直接受到数据质量的影响。因此&#xff0c;数据预处理在数据挖掘中扮演着至关重要的角色。让我们探讨数据质量对数据挖掘结果的影响&#xff0c;并介绍常见的数据预处理方法以及它们如何提…...

Java并发编程—JUC线程池架构

Java并发编程&#xff08;JUC&#xff0c;Java Utilities Concurrency&#xff09;中的线程池架构是Java提供的一种用于管理和复用线程的机制。线程池的主要目标是减少线程创建和销毁的开销&#xff0c;提高系统的响应速度&#xff0c;并通过合理的线程管理和资源分配&#xff…...

Android input输入子系统

一.Android input输入子系统简介 Input系统是Android系统中负责处理用户输入操作的核心组件&#xff0c;它负责从各种输入设备&#xff08;如屏幕、键盘、鼠标等&#xff09;获取原始的输入事件&#xff08;如按键、触摸、滑动等&#xff09;&#xff0c;并将其转换为Android应…...

如何在webapp中于动发布一个应用

目录 第一步&#xff1a;在webapp文件夹内自定义文件夹第二步&#xff1a;生成一个文本&#xff0c;并把后缀改为 .html第三步&#xff1a;进入bin文件夹打开服务第四步&#xff1a;打开方式选择java第六步&#xff1a;输入你想输出的东西第七步&#xff1a;双击运行即可 第一步…...

部署一个本地的ChatGPT(Ollama)

一 下载Ollama Ollama下载地址&#xff1a;https://ollama.com/download 下载完后 二 安装运行 双击下载好的OllamaSetup.exe开发 安装Ollama: 安装完成后&#xff0c;多了一个Ollama的菜单如下图 &#xff1a; Ollama安装好默认是配置开机运行&#xff0c;如果没有运行可以在…...

Vue 3中的reactive:响应式状态的全面管理

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

【网络】详解HTTPS及探究加密过程

目录 一、什么是HTTPS1、加密解密是什么2、为什么要加密3、常见的加密方式1、对称加密2、非对称加密 二、探究HTTPS如何实现加密1、方案一----只使用对称加密2、方案二----只使用非对称加密3、方案三----双方都使用非对称加密4、方案四----非对称加密 对称加密5、中间人攻击6、…...

【C语言】字符与字符串---从入门到入土级详解

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C语言 ⚙️操作环境:Visual Studio 2022 目录 一.字符类型和字符数组&#xff08;串&#xff09;简介 1.ASCII 2.定义&#xff0c;初始化&#xff0c;使用 1>字符的定义及初始化 2>字符串的定义及初始化 二.…...

Github Copilot 工具,无需账号,一键激活

① 无需账号&#xff0c;100%认证成功&#xff01;0风险&#xff0c;可联网可更新&#xff0c;&#xff0c;支持copilot版本升级&#xff0c;支持chat ② 支持windows、mac、linux系统等设备 ③一号通用&#xff0c;支持所有IDE(AppCode,CLion,DataGrip,GoLand,IntelliJ IDEA …...

node: -max-old-space-size=xxx is not allowed in NODE_OPTIONS

问题描述 在启动node项目时&#xff0c;出现了OOM参照网上的处理方案&#xff0c;设置了环境变量&#xff1a; export NODE_OPTIONS"–max-old-space-size8192"当再次通过npm run docs:dev运行node项目的时候出现了如下错误&#xff1a; node: -max-old-space-siz…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...