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

news2025/1/15 23:40:27

一、概述

本节主要讲解在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.coloradmin.cn/o/1513738.html

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

相关文章

MySQL实战:问题排查与监控

常见问题 有更合适的索引不走&#xff0c;怎么办&#xff1f; MySQL在选取索引时&#xff0c;会参考索引的基数&#xff0c;基数是MySQL估算的&#xff0c;反映这个字段有多少种取值&#xff0c;估算的策略为选取几个页算出取值的平均值&#xff0c;再乘以页数&#xff0c;即…

经验分享:专业知识库的搭建秘诀都在这里啦!

我想必每个人都有过被一堆纷繁复杂的信息搞得头疼不已的时候&#xff0c;对吧&#xff1f;那么你是否想过&#xff0c;如果我们有一个专门收藏整理这些信息的地方&#xff0c;会变得多么方便呢&#xff1f;这就是知识库的作用。所以&#xff0c;接下来我就要向大家分享如何搭建…

如何设计一个高并发的系统--简谈

设计一个高并发系统可以从下面这些角度来考虑。 所谓设计高并发系统&#xff0c;就是设计一个系统&#xff0c;保证它整体可用的同时&#xff0c;能够处理很高的并发用户请求&#xff0c;能够承受很大的流量冲击。 我们要设计高并发的系统&#xff0c;那就需要处理好一些常见…

【MySQL】-知识点整理

1、存储引擎 -- 查询数据库支持的存储引擎 show engines; -- 查询当前数据库使用的存储引擎 show variables like %storage_engines%; 主要的存储引擎说明&#xff1a; 1&#xff09;MyISAM&#xff1a;无外键、表锁、所有索引都是非聚簇索引、无事务、记录表总条数、删除表…

Realsense 相机SDK学习(一)——librealsense使用方法及bug解决(不使用Ros)

一.介绍 realsense相机是一个intel开发出来的一款深度相机&#xff0c;我之前使用他来跑过slam&#xff0c;也配置过他的驱动&#xff0c;在此附上realsense的相机驱动安装方法&#xff1a;Ubuntu20.04安装Intelrealsense相机驱动&#xff08;涉及Linux内核降级&#xff09; …

支持S/MIME证书的邮件客户端有哪些?

S/MIME证书&#xff0c;也叫做邮件安全证书&#xff0c;支持安全/多用途互联网邮件扩展协议&#xff08;S/MIME协议&#xff09;&#xff0c;是通过加密和数字签名来确保电子邮件的安全性、保密性和完整性的数字证书。GDPR、HIPAA、FDA等多个行业都要求邮件发送方在发送邮件时对…

EasyPoi 教程

文章目录 EasyPoi教程文档1. 前传1.1 前言 这个服务即将关闭,文档迁移到 http://www.wupaas.com/ 请大家访问最新网站1.2 Easypoi介绍1.3 使用1.4 测试项目1.5 可能存在的小坑 2. Excel 注解版2.1 Excel导入导出2.2 注解注解介绍ExcelTargetExcelEntityExcelCollectionExcelIgn…

如何在群晖NAS部署WPS容器并实现无公网IP远程访问本地office软件

文章目录 1. 拉取WPS Office镜像2. 运行WPS Office镜像容器3. 本地访问WPS Office4. 群晖安装Cpolar5. 配置WPS Office远程地址6. 远程访问WPS Office小结 7. 固定公网地址 wps-office是一个在Linux服务器上部署WPS Office的镜像。它基于WPS Office的Linux版本&#xff0c;通过…

Express学习(四)

使用Express写接口 创建基本的服务器 创建API路由模块 编写GET接口 编写POST接口 CORS跨域资源共享 什么是CORS CORS由一系列HTTP响应头组成&#xff0c;这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源。浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如…

AI论文速读 | TPLLM:基于预训练语言模型的交通预测框架

论文标题&#xff1a;TPLLM: A Traffic Prediction Framework Based on Pretrained Large Language Models 作者&#xff1a;Yilong Ren&#xff08;任毅龙&#xff09;, Yue Chen, Shuai Liu, Boyue Wang&#xff08;王博岳&#xff09;,Haiyang Yu&#xff08;于海洋&#x…

【Linux进程的知识点】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档文章目录 前言 操作系统的知识补充 我们来理解一个用户操作接口&#xff1a; 进程的理解 进程的基本概念 描述进程-PCB task_struct-PCB的一种 task_ struct内容分类 …

【四】【算法分析与设计】贪心算法的初见

455. 分发饼干 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有…

Terrace联合创始人兼CEO Jesse Beller确认出席Hack.Summit() 2024区块链开发者大会

在科技创新的浪潮中&#xff0c;区块链技术以其独特的去中心化、透明性和安全性&#xff0c;正逐渐成为引领未来发展的重要力量。在这样的背景下&#xff0c;备受瞩目的Hack.Summit() 2024区块链开发者大会即将于4月9日至10日在香港数码港盛大举行。本次大会的亮点之一&#xf…

Linux系统安全②SNAT与DNAT

一.SNAT 1.定义 利用SNAT技术实现2台私网地址都可以访问公网 2.实验环境准备 &#xff08;1&#xff09;三台服务器&#xff1a;PC1客户端、PC2网关、PC3服务端。 &#xff08;2&#xff09;硬件要求&#xff1a;PC1和PC3均只需一块网卡、PC2需要2块网卡 &#xff08;3&a…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)中篇

onBeforeUnload onBeforeUnload(callback: (event?: { url: string; message: string; result: JsResult }) > boolean) 刷新或关闭场景下&#xff0c;在即将离开当前页面时触发此回调。刷新或关闭当前页面应先通过点击等方式获取焦点&#xff0c;才会触发此回调。 参数…

docker部署多功能网络工具箱

功能 查看自己的IP&#xff1a;从多个 IPv4 和 IPv6 来源检测显示本机的IP 查看IP信息&#xff1a;显示所有 IP 的相关信息 可用性检测&#xff1a;检测一些网站的可用性 WebRTC 检测&#xff1a;查看使用 WebRTC 连接时使用的 IP DNS 泄露检测&#xff1a;查看 DNS 出口信息 …

NVMFS5A160PLZT1G汽车级功率MOSFET P沟道60 V 15A 满足AEC-Q101标准

关于汽车电子AEC Q101车规认证&#xff1f; 是一种针对分立半导体的可靠性测试认证程序&#xff0c;由汽车电子协会发布。这个认证程序主要是为了确保汽车电子产品在各种严苛的条件下能够正常工作和可靠运行。它包括了对分立半导体的可靠性、环境适应性、温度循环和湿度变化等…

STM32平替GD32有多方便

众所周知, GD32一直模仿STM32,从未被超越。 我最近公司使用的GD32E230C6T6 这款芯片有48个引脚。 属于小容量的芯片。 我有一个用STM32写的代码,之前是用的 STM32F103CB 这款芯片是中容量的。 不过在keil中,只需要这两步,就能使用原来的逻辑,几乎不用修改代码。 1. …

武汉儿童医院变电所电力运维平台系统的设计及应用

彭姝麟 Acrelpsl 1 引言 2015年国务院发布《中共中央、国务院关于进一步深化电力体制改革的若干意见》&#xff08;中发[2015]9号&#xff09;&#xff0c;简称“电改9号文”。而本次新电改的重点是“三放开一独立三强化”&#xff1a;输配以外的经营性电价放开、售电业务放开…

APP测试基本流程以及APP测试要点

一、 APP测试基本流程 1、流程图 2、测试周期 测试周期可按项目的开发周期来确定测试时间&#xff0c;一般测试时间为两三周&#xff08;即15个工作日&#xff09;&#xff0c;根据项目情况以及版本质量可适当缩短或延长测试时间。 3、测试资源 测试任务开始前&#xff0c;…