首页 > 编程知识 正文

socketio支持socket,Socketio

时间:2023-05-05 17:51:35 阅读:224360 作者:1164

socketio实现方式 一、后端实现 1.1、基本实现 导入依赖 <dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.11</version></dependency> SocketIo配置

SocketIo启动

消息实现类 SocketIoHandler

下面详细说明

后端大概就这些代码了,很简洁的,多的就没有。

1.2、消息处理类 监听客户端连接

客户端连接成功是调用。

在方法上面打上 @OnConnect注解,表示监听连接情况,这个方法传入 SocketIOClient对象,获取连接这个客户端的信息。

这里最主要获取客户端的 sessionID和客户的唯一标识,其实这个sessionID就是一个 java.util.UUID对象,但是指定用户发送信息是需要用到,所以在这里就拿到它并保存到Map集合中。

这里我们做的不多,就是获取一个UUID和用户唯一标识。这些都是String类型的,如果用户量比较大的情况下,我们可以存入Redis中,不要存在这个Map集合了。

监听客户端断开

客户端断开连接时调用。

在方法上打上 @OnDisconnect注解,表示监听客户端是否断开。同样需要 SocketIOClient对象,当客户端断开时可以获取到sessionID和用户唯一标识等客户端信息。但是我觉得只要获取到用户唯一标识就足够了,因为sessionID在连接成功就拿到并保存了的。

客户端断开了,获取到客户唯一标识并在保存客户端信息这里面删除,这里是保存在map集合中,那么就在这个集合中删除就OK。删除就标识不在线啦。

监听客户端名为某个事件的信息

客户端代码应该是这样的。

socket.emit("事件名","参数数据")方法,是触发后端自定义消息事件的时候使用的

当事件名为 roomMessageSending这个时发送的数据就会在这里被调用,这里也可以获取到客户端的相关信息,和客户端传过来的数据。这个事件名是随便写的,数据也可以是其他形式的,比如对象 ,前端平时对象是怎么赋值的就怎么赋值。

给指定的客户发送信息

关键就是这一句

// 获取对象@Autowiredprivate SocketIOServer socketIOServer;socketIOServer.getClient(roomMap.get(roomId)).sendEvent(roomId, data) ;

roomMap.get(roomId)根据你要发送信息给哪个客户,那么就将这个客户的唯一标识穿过来,利用这个唯一标识就可以在Map集中获取sessionID,就是在连接成功时获取的那个UUID,

sendEvent(roomId, data),roomId客户的唯一标识,data需要穿的数据,当然也可以是其他数据类型。

二、前端实现

安装 socket.io

npm install --save socket.io-client

引入socket import sio from "socket.io-client"; 注意这两个生命周期 /** * 加载组件执行 * 是数据挂载后的生命周期函数 */ mounted() { this.connect(); }, /** * 关闭组件执行 * 实例销毁后 */ destroyed() { this.socketIoClient.close(); },

mounted()数据已经挂在到模板中,这时执行 connect()这个方法,让socketIo的信息,并将这个对象保存,方便后面使用。

完整代码 <template> <div> <h2 ref="SendMsg"> <ul> <li v-for="(item, index) in itemArr" :key="index">{{ item }}</li> </ul> </h2> <input type="text" v-model="msg" /> <button @click="sendMsg">发送</button> </div></template> <script>import sio from "socket.io-client";export default { name: "HelloWorld", data() { return { socketIoClient: null, itemArr: ["欢迎来到WIM1000聊天室"], roomId: "WIM1000", msg: "", }; }, methods: { connect() { this.socketIoClient = sio.connect( "http://192.168.124.7:9092?roomId=" + this.roomId ); // 服务器连接成功调用 this.socketIoClient.on("connect", function () { console.log("连接了服务器"); }); // 监听当前用户唯一标识的这个事件名,用户发送信息就靠这个事件名来接收。 this.subscription(); }, subscription() { let vm = this; // socket.on("事件名",匿名函数(服务器向客户端发送的数据))为监听服务器端的事件 this.socketIoClient.on(this.roomId, function (data) { // 这是服务器端发送的信息 console.log(data); vm.itemArr.push(data); }); }, sendMsg() { // socket.emit("事件名","参数数据")方法,是触发后端自定义消息事件的时候使用的, this.socketIoClient.emit("roomMessageSending", this.msg); }, }, /** * 加载组件执行 * 是数据挂载后的生命周期函数 */ mounted() { this.connect(); }, /** * 关闭组件执行 * 实例销毁后 */ destroyed() { this.socketIoClient.close(); },};</script> 三、测试效果 整个过程分析

this.socketIoClient.on(this.roomId, function (data)这里监听的是当前自己这个用户的,因为是用自己的唯一标识作为监听函数名的。

socketIOServer.getClient(roomMap.get(roomId)).sendEvent(roomId, data) ;那个用户发来的数据就将客户的唯一标识作为监听函数推数据过去。

测试

因为我前端部署了两套一模一样的,模拟两个人。

将前后端都启动起来。

四、业务设计描述

如果在线人数非常多的情况下,后天将用户登录的sessionID就是那个UUID和用户的唯一标识保存在Map集合中是不现实的,建议保存在Redis中。用户唯一标识可以作为key,回话UUID作为value。当设置用户表的时候,用户ID用分布式ID策略生成。前端登录成功后就可以获取到自己的ID,然后在前端就可以作为自己的用户唯一标识了。当登录成功时,可以将所有在线的客户存入一个Redis库中,需要使用时就直接在这个Redis库中查询。客户单连接失败了,就说明已经下线了,就在这张Redis库中删除用户信息。但是需要注意,如果同一个用户在不同机器上登录呢?用户的这个唯一标识是不是不能直接作为Redis的key,这个key需要在加工处理。

但是当其他用户想要给没有在线的用户发送信息,这时我们发现目标用户已经不在线了。可以将需要发送的这些信息保存到消息队列中,当目标用户上线我们在发送给目标用户。

五、广播式发送消息

今后可以将订阅的事件名和数据都写成动态的,用户需要开启什么监听直接传入动态的数据进来就行了。关键订阅了这个事件名保存在哪里呢?跟踪代码后发现,最终这里的订阅的事件名都是保存在集合中的,所以不合适开启的订阅事件名过多。

测试

将两个客户端你都启动,但是一个都不订阅的情况下,在后端发送一个text订阅。两个客户端都没有收到任何数据,说明OK。

将客户唯一标识为 WIM2000的开启订阅,在后端发送一个订阅请求。

将两个都开启订阅,这样两个都收到text的订阅信息。

噢啦,暂时就讲解到这里。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。