第五节:使用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动作,需要在这里进行逻辑分流,具体代码是:

java 复制代码
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:客户端连接服务器的处理逻辑。

java 复制代码
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:客户端关闭的逻辑处理。

java 复制代码
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:消息收到后的处理逻辑。

java 复制代码
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代码

javascript 复制代码
<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代码

javascript 复制代码
<!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组件的操控,代码如:

java 复制代码
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组件代码

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

java 复制代码
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几个系统的消息对接和众多业务场景设计,稳定、准确运行。

相关推荐
李慕婉学姐3 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
じ☆冷颜〃3 小时前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
懒人村杂货铺4 小时前
✅ WebSocket 接口从本地开发到生产部署的关键步骤与常见问题
websocket
风送雨4 小时前
FastMCP 2.0 服务端开发教学文档(下)
服务器·前端·网络·人工智能·python·ai
芯盾时代4 小时前
石油化工行业网络风险解决方案
网络·人工智能·信息安全
线束线缆组件品替网5 小时前
Weidmüller 工业以太网线缆技术与兼容策略解析
网络·人工智能·电脑·硬件工程·材料工程
奋进的芋圆5 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin5 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20055 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉5 小时前
JavaBean相关补充
java·开发语言