三分钟看懂webSocket单发、群发、心跳检测机制

三分钟看懂webSocket单发、群发、心跳检测机制


前言

该文章主要讲解webSocket如何应用,单发、群发、心跳检测机制如何实现

一、什么是webSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议,这也是其最大特点,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种

二、使用步骤

1.搭建Springboot项目、导入相关POM

springBoot

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-websocket</artifactId>
	</dependency>

2.编辑application.yml

server:
  port: 81
spring:
  thymeleaf:
    cache: false
    encoding: UTF-8
    mode: LEGACYHTML5
    prefix: classpath:/templates/
    suffix: .html
    check-template-location: true
  devtools:
    restart:
      enabled: true
  mvc:
    static-path-pattern: /static/**
  

3.编辑ws.js文件

(function($) {
	//打开连接
	$.connect = function(url) {
		// 自动处理前缀
		var protocol = (window.location.protocol == 'http:') ? 'ws:' : 'wss:';
		this.host = protocol + url;

		window.WebSocket = window.WebSocket || window.MozWebSocket;
		if (!window.WebSocket) { // 检测浏览器支持
			this.error('Error: WebSocket is not supported .');
			return;
		}
		// 创建连接
		this.socket = new WebSocket(this.host);
		// 注册响应函数 onopen, onmessage, onclose, onerror
		this.socket.onopen = function() {
			$.onopen();
		};
		this.socket.onmessage = function(message) {
			$.onmessage(message);
		};
		this.socket.onclose = function() {
			$.onclose();
			$.socket = null;
		};
		this.socket.onerror = function(errorMsg) {
			$.onerror(errorMsg);
		}
		return this;
	}
	//自定义异常函数
	$.error = function(errorMsg) {
		this.onerror(errorMsg);
	}
	//消息发送
	$.send = function(message) {
		if (this.socket) {
			this.socket.send(message);
			return true;
		}
		this.error('please connect to the server first !!!');
		return false;
	}
	//关闭连接
	$.close = function() {
		if (this.socket != undefined && this.socket != null) {
			this.socket.close();
		} else {
			this.error("this socket is not available");
		}
	}
	//消息回調
	$.onmessage = function(message) {
		console.log("default callback : receive msg : " + message.data);
	}
	//链接回调函数
	$.onopen = function() {
		console.log("websocket open success !");
	}
	//关闭回调
	$.onclose = function() {
		console.log("websocket close success !");
	}
	//异常回调
	$.onerror = function() {
		console.log("error happened !");
	}

})(ws = {});

4.编辑webClient.html文件

这边就简简单单一个输入框及发送按钮,就不做啥界面美化哈…

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我是web客户端</title>
</head>
<body>
我是web客户端
<input id="text"/>
<button onclick="sendText()">发送</button>

</body>
<script type="text/javascript" src="/static/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="/static/js/ws.js"></script>
<script type="text/javascript">
//只局限于本机通讯的话可以localhost,若是局域网访问的话,需更换本机的IPV4地址
var addr="/192.168.0.106:81/websocket"
 $(function() {
    reconnect();
    ws.onmessage = function(msg) {
    var info=msg.data;
    console.log("来自服务器的消息:"+info);
    if(msg.data=="ok"){
      console.log("心跳检测OK");
      heartCheck.reset();
    }
    }
 })
 function reconnect(){
	 console.log("连接中");
	 ws.connect(addr);// 后台接口地址
 }
 function sendText(){
 var msg=$("#text").val();
 ws.send(msg);
 }
 //心跳检测
  var heartCheck = {
    timeout: 10000,//10ms
    timeoutObj: null,
    serverTimeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
     this.start();
    },
    start: function(){
        var self = this;
        this.timeoutObj = setTimeout(function(){
            ws.send("ok");
            self.serverTimeoutObj = setTimeout(function(){
              //ws.close();//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
            }, self.timeout)
        }, this.timeout)
    },
}
ws.onopen = function () {
  console.log("心跳检测开启");
   heartCheck.start();
};
ws.onclose = function () {
	console.log("连接关闭");
    reconnect();
};
ws.onerror = function () {
	console.log("服务器连接异常,请重试");
};
</script>
</html>

5.编辑WebSocketUtil工具类

实现socket的单发、群发、心跳检测等功能

package com.mm.utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;
/**
 * 
 * @author MWEI Email:574185505@qq.com
 * @version 2021年06月16日 下午1:50:34 Class Explain 页面js文件调用的websocket访问路径
 */
@Component
@ServerEndpoint("/websocket")
public class WebSocketUtil {
	// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
	private static int onlineCount = 0;
	// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
	public static CopyOnWriteArraySet<Session> webSockets = new CopyOnWriteArraySet<Session>();
	/**
	 * 连接建立成功调用的方法
	 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
	 */
	@OnOpen
	public void onOpen(Session session) {
		webSockets.add(session);
		addOnlineCount(); // 在线数加1
		System.out.println("有新连接加入!当前连接页面为" + getOnlineCount() + " --> " + session.getId());
	}
	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose(Session session) {
		webSockets.remove(session);
		subOnlineCount(); // 在线数减1
		System.out.println("有一连接关闭!当前连接页面为" + getOnlineCount());
	}
	/**
	 * @param message 客户端发送过来的消息
	 * @param session 可选的参数
	 */
	@OnMessage
	public void onMessage(String message, Session session) throws IOException {
		System.out.println("来自客户端的消息:" + message + "\tsession:" + session);
		if (message.equals("ok")) {
			// 心跳检测
			sendToCurr(message, session);
		} else {
			sendToAll(message);
		}
	}

	/**
	 *  群发消息
	 * @param message
	 */
	public static void sendToAll(String message) {
		for (Session item : webSockets) {
			try {
				// System.out.println("发送消息给" + item);
				item.getAsyncRemote().sendText(message);
			} catch (Exception e) {
				e.printStackTrace();
				continue;
			}
		}
	}
	/**
	 *  发送给当前连接用户
	 * @param message
	 */
	public static void sendToCurr(String message,Session session) {
		session.getAsyncRemote().sendText(message);
	}
	/**
	 * 发生错误时调用
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		System.out.println("发生错误");
		error.printStackTrace();
	}
	public static synchronized int getOnlineCount() {
		return onlineCount;
	}
	private static synchronized void addOnlineCount() {
		WebSocketUtil.onlineCount++;
	}
	private static synchronized void subOnlineCount() {
		WebSocketUtil.onlineCount--;
	}

}

6.编辑WebSocketConfig配置类

若是打成war包部署在tomcat中的话不需要这个bean

package com.mm.utils;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
}

7.编辑webController类

实现页面的跳转

package com.mm.controller;
import  org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class webController {
    @RequestMapping("/")
    public String toWebClient() {
        return "/web/webClient";
    }
}

8.效果图如下

在这里插入图片描述

9.项目结构如下

在这里插入图片描述


总结

以上就是今天要讲的内容,本文仅简单介绍了webSocket的使用,感谢支持,谢谢

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要实现在 React Native 中建立 WebSocket 连接并进行心跳检测,可以参考以下步骤: 1. 安装 `react-native-websocket` 库 ``` npm install --save react-native-websocket ``` 2. 在需要使用 WebSocket 的组件中导入并创建 WebSocket 实例,并添加心跳检测逻辑 ```javascript import React, { Component } from 'react'; import { View } from 'react-native'; import WebSocket from 'react-native-websocket'; class MyComponent extends Component { constructor(props) { super(props); this.state = { ws: null, }; } componentDidMount() { const ws = new WebSocket('ws://localhost:3000'); this.setState({ ws }); // 心跳检测 ws.onopen = () => { console.log('WebSocket connected'); this.pingInterval = setInterval(() => { if (ws.readyState === ws.OPEN) { ws.send(JSON.stringify({ type: 'ping' })); } }, 5000); }; // 接收服务端消息 ws.onmessage = (evt) => { console.log(`Received message: ${evt.data}`); }; // WebSocket 断开处理 ws.onclose = () => { console.log('WebSocket closed'); clearInterval(this.pingInterval); }; } componentWillUnmount() { const { ws } = this.state; if (ws) { ws.close(); clearInterval(this.pingInterval); } } render() { return <View />; } } export default MyComponent; ``` 在上述代码中,我们创建了一个 WebSocket 实例,并在 `componentDidMount` 生命周期钩子中添加了心跳检测逻辑。这里我们使用了 `setInterval` 定时发送 `ping` 消息,并在 `onmessage` 回调中处理服务端返回的消息。在 `onclose` 回调中清除定时器。 3. 注意事项 - 在组件卸载时,需要关闭 WebSocket 连接并清除心跳检测定时器,以免引起内存泄漏; - 心跳检测的时间间隔需要根据具体业务需求进行调整; - 需要注意处理 WebSocket 连接异常情况,例如网络异常或服务端关闭连接等;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值