socket.io在springboot中的使用
-
pom引用
<dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.11</version> </dependency>
-
properties
socketIo.host=192.168.1.133 socketIo.port=9092 # 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器 socketIo.maxFramePayloadLength=1048576 # 设置http交互最大内容长度 socketIo.maxHttpContentLength=1048576 # socket连接数大小(如只监听一个端口boss线程组为1即可) socketIo.bossCount=1 socketIo.workCount=100 socketIo.allowCustomRequests=true # 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间 socketIo.upgradeTimeout=1000000 # Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件 socketIo.pingTimeout=6000000 # Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔 socketIo.pingInterval=25000
-
SocketIOServer连接配置
package com.example.socketio.config; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.SpringAnnotationScanner; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class NettySocketConfig { @Value("${socketIo.host}") private String host; @Value("${socketIo.port}") private int port; @Value("${socketIo.maxFramePayloadLength}") private int maxFramePayloadLength; @Value("${socketIo.maxHttpContentLength}") private int maxHttpContentLength; @Value("${socketIo.bossCount}") private int bossCount; @Value("${socketIo.workCount}") private int workCount; @Value("${socketIo.allowCustomRequests}") private boolean allowCustomRequests; @Value("${socketIo.upgradeTimeout}") private int upgradeTimeout; @Value("${socketIo.pingTimeout}") private int pingTimeout; @Value("${socketIo.pingInterval}") private int pingInterval; @Bean public SocketIOServer socketIOServer() throws Exception { com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration(); config.setHostname(host); config.setPort(port); config.setMaxFramePayloadLength(maxFramePayloadLength); config.setMaxHttpContentLength(maxHttpContentLength); config.setBossThreads(bossCount); config.setWorkerThreads(workCount); config.setAllowCustomRequests(allowCustomRequests); config.setUpgradeTimeout(upgradeTimeout); config.setPingTimeout(pingTimeout); config.setPingInterval(pingInterval); //该处进行身份验证 config.setAuthorizationListener(handshakeData -> { return true; }); final SocketIOServer server = new SocketIOServer(config); return server; } //开启注解 @Bean public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) { return new SpringAnnotationScanner(socketServer); } }
-
启动SocketIo
package com.example.socketio.socketio; import com.corundumstudio.socketio.SocketIOServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** * SocketIo启动类 */ @Component @Order(value = 1) public class SocketIoRun implements CommandLineRunner { @Autowired private SocketIOServer socketIOServer; @Override public void run(String... args) throws Exception { socketIOServer.start(); System.out.println("socket.io启动成功!"); } }
socket.io在Vue中的使用
-
引入socket.io-client
npm install --save socket.io-client
-
使用
<template> <div> <h1>{{ msg }}</h1> <button @click="connect">连接</button> </div> </template> <script> import Socketio from "socket.io-client"; export default { name: 'HelloWorld', data () { return { socketIoClient: null, msg: 'Welcome to Your Vue.js App' } }, methods: { connect(){ this.socketIoClient = Socketio.connect('http://192.168.1.133:9092') //监听与服务器的连接状态 this.socketIoClient.on("connect",function(){ console.log("连接了服务器") }) } }, mounted: { } } </script>
广播式订阅
-
java后端发布广播
package com.example.socketio.controller; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Collection; @Controller @RequestMapping(value = "/socketIoTest") public class SocketIoTestController { @Autowired private SocketIOServer socketIOServer; @RequestMapping(value = "/broadcast") public void broadcast() { //广播式发送消息 //向所以订阅了名为text事件的客户端发送消息 Collection<SocketIOClient> allClients = socketIOServer.getAllClients(); allClients.parallelStream().forEach(x -> { x.sendEvent("text", "Hello socketIo!"); }); } }
-
vue前端代码
<template> <div> <h1>{{ msg }}</h1> <button @click="connect">连接</button> <button @click="subscription">订阅</button> <button @click="callOffMsg">取消订阅</button> </div> </template> <script> import Socketio from "socket.io-client"; export default { name: 'HelloWorld', data () { return { socketIoClient: null, msg: 'Welcome to Your Vue.js App' } }, methods: { connect(){ this.socketIoClient = Socketio.connect('http://192.168.1.133:9092') this.socketIoClient.on("connect",function(){ console.log("连接了服务器") }) }, //订阅text事件 subscription(){ console.log("订阅了text事件") this.socketIoClient.on('text', function (data) { console.log(data) }) }, //取消text事件订阅 callOffMsg(){ console.log("取消了事件的订阅") this.socketIoClient.removeAllListeners("text"); } }, mounted: { } } </script>
聊天室
-
java后端代码
package com.example.socketio.socketio; import com.corundumstudio.socketio.AckRequest; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnEvent; import io.netty.util.internal.StringUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListSet; /** * 消息处理类实现 */ @Component public class SocketIoHandler { @Autowired private SocketIOServer socketIOServer; private static ConcurrentHashMap<String, ConcurrentSkipListSet> roomMap = new ConcurrentHashMap(); //监听客户端连接 @OnConnect public void onConnect(SocketIOClient client) { System.out.println(client.getRemoteAddress() + "-------------------------" + "客户端已连接"); UUID sessionId = client.getSessionId(); String roomId = client.getHandshakeData().getSingleUrlParam("roomId"); if (StringUtil.isNullOrEmpty(roomId)) { return; } ConcurrentSkipListSet<UUID> concurrentSkipListSet = roomMap.get(roomId); if (concurrentSkipListSet == null || concurrentSkipListSet.isEmpty()) { concurrentSkipListSet = new ConcurrentSkipListSet(); } concurrentSkipListSet.add(sessionId); roomMap.putIfAbsent(roomId, concurrentSkipListSet); } //监听客户端断开 @OnDisconnect public void onDisconnect(SocketIOClient client) { System.out.println(client.getRemoteAddress() + "-------------------------" + "客户端已断开连接"); UUID sessionId = client.getSessionId(); String roomId = client.getHandshakeData().getSingleUrlParam("roomId"); if (StringUtil.isNullOrEmpty(roomId)) { return; } ConcurrentSkipListSet<UUID> concurrentSkipListSet = roomMap.get(roomId); if (concurrentSkipListSet == null || concurrentSkipListSet.isEmpty()) { return; } concurrentSkipListSet.remove(sessionId); roomMap.putIfAbsent(roomId, concurrentSkipListSet); } //监听名为roomMessageSending的请求事件 @OnEvent(value = "roomMessageSending") public void onEvent(SocketIOClient client, AckRequest ackRequest, String data) { String roomId = client.getHandshakeData().getSingleUrlParam("roomId"); if (StringUtil.isNullOrEmpty(roomId)) { return; } ConcurrentSkipListSet<UUID> concurrentSkipListSet = roomMap.get(roomId); if (concurrentSkipListSet == null || concurrentSkipListSet.isEmpty()) { return; } concurrentSkipListSet.forEach(x -> socketIOServer.getClient(x).sendEvent(roomId, data)); } }
-
vue前端代码
<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", userName: "", msg: '', } }, methods: { connect(){ this.socketIoClient = sio.connect('http://192.168.1.133:9092?roomId='+this.roomId) this.socketIoClient.on("connect",function(){ console.log("连接了服务器") }) this.subscription() }, subscription(){ let vm = this this.socketIoClient.on(this.roomId, function (data) { console.log(data) vm.itemArr.push(data) }) }, sendMsg(){ this.socketIoClient.emit("roomMessageSending",this.userName+ ": " + this.msg); } }, //加载组件执行 mounted() { this.userName = "jaye" this.connect() }, //关闭组件执行 destroyed() { this.socketIoClient.close() } } </script>