第五节:使用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几个系统的消息对接和众多业务场景设计,稳定、准确运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/748414.shtml

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

相关文章

pytorch升级打怪(三)

数据集合数据加载器 简介加载数据集迭代和可视化数据集为您的文件创建自定义数据集__init____len____getitem__ 准备您的数据以使用DataLoaders进行训练通过DataLoader进行遍载 简介 处理数据样本的代码可能会变得混乱且难以维护&#xff1b;理想情况下&#xff0c;我们希望我…

N7977A 先进电源系统:动态直流电源,160 V,12.5 A,2000 W

N7977A 先进电源系统&#xff1a;动态直流电源 160 V&#xff0c;12.5 A&#xff0c;2000 W Keysight N7977A 专为需要高速动态电源和测量功能的自动化测试设备&#xff08;ATE&#xff09;应用而设计。 简述 支持 BenchVue 软件。 无需编程&#xff0c;即可结合使用您的计…

NCP1271D65R2G中文资料规格书PDF数据手册引脚图参数图片价格功能特性描述

产品描述&#xff1a; NCP1271 是成功的 7 引脚电流模式 NCP12XX 系列的新一代引脚-引脚兼容新产品。该控制器通过使用可调节 Soft Skip 模式和集成的高电压启动 FET&#xff0c;实现了卓越的待机功耗。此专属 Soft Skip 还大大降低了噪音的风险。 因此可以在箝位网络中使用不…

模型蒸馏--一起学习吧之人工智能

一、定义 模型蒸馏&#xff08;Model Distillation&#xff09;是一种模型压缩技术&#xff0c;旨在将一个复杂的大型模型&#xff08;通常称为教师模型&#xff09;的知识转移到另一个更小、更简单的模型&#xff08;通常称为学生模型&#xff09;中。这种技术通过训练学生模…

如何在代理的IP被封后立刻换下一个IP继续任务

目录 前言 1. IP池准备 2. 使用代理IP进行网络请求 3. 处理IP被封的情况 4. 完整代码示例 总结 前言 当进行某些网络操作时&#xff0c;使用代理服务器可以帮助我们隐藏真实IP地址以保护隐私&#xff0c;或者绕过一些限制。然而&#xff0c;经常遇到的问题是代理的IP可能…

BlenderGIS 快捷键E 报错问题 Report: Error

最新版的Blender4.0 对于 BlenderGIS2.28版本的插件不兼容&#xff0c;BlenderGIS2.28兼容Blender3.6.9及之前的版本&#xff0c;应该是BlenderGIS插件很久没更新了导致的。

C#构建类库

类库程序集能将类型组合成易于部署的单元&#xff08;DLL文件&#xff09;&#xff0c;为了使编写的代码能够跨多个项目重用&#xff0c;应该将他们放在类库程序集中。 一、创建类库 在C#中&#xff0c;构建类库是指创建一个包含多个类的项目&#xff0c;这些类可以被其他应用…

热流道融合3D打印技术正在成为模具制造新利器

在模具领域中&#xff0c;3D打印技术与热流道技术联手&#xff0c;能迸发出更耀眼的光芒。两种技术虽然各有特点&#xff0c;但两者结合将形成互补作用&#xff0c;从而实现11&#xff1e;2”的跨越式提升。 将增材制造的灵活思维融入传统模具设计时&#xff0c;不仅能够突破传…

王勇:硬科技的下一站 | 演讲嘉宾公布

一、智能耳机与可穿戴专题论坛 智能耳机与可穿戴专题论坛将于3月27日同期举办&#xff01; 智能耳机、可穿戴设备已经逐渐融入我们的生活&#xff0c;它们不仅带来了便捷与舒适&#xff0c;更在悄然改变着我们的生活方式和工作模式。在这里&#xff0c;我们将分享最新的研究成果…

别再手动拼接 SQL 了,MyBatis 动态 SQL 写法应有尽有,建议收藏!

一、MyBatis动态 sql 是什么 动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中&#xff0c;开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。 例如&#xff0c;拼接时要确保添加了必要的空格&#xff0c;还要注意去掉…

[SaaS] 淘宝设AI

“淘宝设计AI” 让国际大牌造世界双11超级品牌 超级发布https://mp.weixin.qq.com/s/xFVDARQHxlweKAYG91DtYw下面是一个完整的品牌营销海报设计流程&#xff0c;AIGC起到了巨大作用&#xff0c;但是仍然很难去一步解决这个问题&#xff0c;还是逐步修改的一个过程。 Midjouner…

分布式与集群,二者区别是什么?

&#x1f413;分布式 分布式系统是由多个独立的计算机节点组成的系统&#xff0c;这些节点通过网络协作完成任务。每个节点都有自己的独立计算能力和存储能力&#xff0c;可以独立运行。分布式系统的目标是提高系统的可靠性、可扩展性和性能。 分布式服务包含的技术和理论 负…

LabVIEW多表位数字温湿度计图像识别系统

LabVIEW多表位数字温湿度计图像识别系统 解决数字温湿度计校准过程中存在的大量需求和长时间校准问题&#xff0c;通过LabVIEW开发平台设计了一套适用于20多个表位的数字温度计图像识别系统。该系统能够通过图像采集、提取和处理&#xff0c;进行字符训练&#xff0c;从而实现…

中小企业的智能化,不能再拖了!

在当今时代&#xff0c;新质生产力已然成为了国内最热门的话题。它代表着先进生产力的涌现和发展&#xff0c;正逐渐成为推动国家经济社会持续发展的核心力量。今年的两会更是将“新质生产力”写入政府工作报告&#xff0c;并将其列为2024年政府工作十大任务之首&#xff0c;足…

【JS】parseInt与Math.floor的区别

获取两数区间随机整数的函数如下 function getRandom(min,max){return Math.floor(Math.random() * (max - min) min) }这个函数中&#xff0c;只可以使用Math.random&#xff0c;parseInt会出问题&#xff0c;二者虽然都是取整&#xff0c;但又有一些区别。 parseInt是「向…

力扣大厂热门面试算法题 30-32

30. 串联所有单词的子串&#xff0c;31. 下一个排列 &#xff0c;32. 最长有效括号&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.15 可通过leetcode所有测试用例。 目录 30. 串联所有单词的子串 解题思路 完整代码 Java …

算法笔记 连载中。。。

HashMap&#xff08;会根据key值自动排序&#xff09; HashMap<String, Integer> hash new HashMap<>() hash.put(15,18) hash.getOrDefault(ts, -1) //如果ts(key)存在&#xff0c;返回对应的value 否则返回-1 hashMap1.get(words1[i])1会报错&#xff0c;因…

AcWing 848. 有向图的拓扑序列

#include<iostream> #include<cmath> #include<queue> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int N1e510; int n,m,a,b; int e[N],ne[N],h[N],idx; int d[N],top[N],cnt1;//top是拓扑排序…

Linux学习笔记:什么是文件描述符

什么是文件描述符 C语言的文件接口文件的系统调用什么是文件描述符,文件描述符为什么是int类型?为什么新打开的文件的文件描述符不是从0开始? 文件描述符 fd (file descriptor) C语言的文件接口 当时学习C语言的时候,学习了文件接口 具体可以查看之前的文章: 链接:C语言的文…

flask库

文章目录 flask库1. 基本使用2. 路由路径和路由参数3. 请求跳转和请求参数4. 模板渲染1. 模板变量2. 过滤器3. 测试器 5. 钩子函数与响应对象 flask库 flask是python编写的轻量级框架&#xff0c;提供Werkzeug&#xff08;WSGI工具集&#xff09;和jinjia2&#xff08;渲染模板…