美文网首页java学习之路
spring boot 整合netty-socketio

spring boot 整合netty-socketio

作者: 唯有努力不欺人丶 | 来源:发表于2020-03-20 10:00 被阅读0次

    其实这个文章写得没啥技术含量,而且网上教程很多。
    但是还是觉得用自己的语言表述出来,以后再用也不用一行代码一行代码的写了,直接cv就行了。

    1.导包
            <!-- netty socketio -->
            <dependency>
                <groupId>com.corundumstudio.socketio</groupId>
                <artifactId>netty-socketio</artifactId>
                <version>1.7.13</version>
            </dependency>
    
    2.代码配置

    这里需要两个配置类(我把socketio的配置信息都写在了类里而不是配置文件中)

    • 启动类
    @Component
    @Order(value=1)
    public class MyCommandLineRunner implements CommandLineRunner {
        private final SocketIOServer server;
    
    
        @Autowired
        public MyCommandLineRunner(SocketIOServer server) {
            this.server = server;
        }
    
    
        @Override
        public void run(String... args) throws Exception {
            server.start();
        }
    }
    
    • 事件处理类
      对于socket服务端来讲,其实事件就几个:
      • 客户端连接
      • 客户端断开
      • 客户端发来消息
      • 给客户端发消息

    然后首先说连接断开发来消息,都是可以知道是哪个客户端的。我这里是设置socket连接的参数 params来分辨是谁的。这里可以用来存具体的用户信息,token啥的都可以。
    最后给客户端发消息大体上分两种:一种给某一个客户端发消息,还有一种是给所有用户或者某一类用户发消息。其实处理是一样的,只不过如果是所有用户则遍历全部客户端。
    然后我直接贴代码:

    @Component
    public class MessageEventHandler {
    
        @Autowired
        public static SocketIOServer socketIoServer;
    
        public static ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>();
    
        @OnConnect
        public void onConnect(SocketIOClient client) {
            String params = client.getHandshakeData().getSingleUrlParam("params");
            System.err.println(params + "已连接上");
            System.err.println(client.getRemoteAddress());
            System.err.println("客户端sessionid" + client.getSessionId());
            // 存储SocketIOClient,用于发送消息
            socketIOClientMap.put(params, client);
    
        }
    
        /**
         * 客户端断开连接
         * 
         * @param client
         */
        @OnDisconnect
        public void onDisconnect(SocketIOClient client) {
            String params = client.getHandshakeData().getSingleUrlParam("params");
            System.err.println(params + "已断开");
            socketIOClientMap.remove(params);
        }
    
        /**
         * 客户端事件
         * 
         * @param client
         * @param request
         * @param data
         */
        @OnEvent(value = "messageevent")
        public void onEvent(SocketIOClient client, AckRequest request, String data) {
    
        }
    
        // 广播消息
        public static boolean sendMsg(String event, String message) {
            for (SocketIOClient client : socketIOClientMap.values()) {
                if (client.isChannelOpen()) {
                    client.sendEvent(event, message);
                }
            }
            return true;
        }
    }
    

    如上,socket基本准备工作完成了,剩下的就是在启动类做一些具体的配置(这个配置可以用配置文件然后在代码中引用,但是我嫌麻烦,是直接在类中写的字面量,推荐配置文件吧)
    socketio配置文件的基本配置:

    # SocketIO配置
    socketio:
        # SocketIO端口
        port: 9090
        # 连接数大小
        workCount: 100
        # 允许客户请求
        allowCustomRequests: true
        # 协议升级超时时间(毫秒),默认10秒,HTTP握手升级为ws协议超时时间
        upgradeTimeout: 10000
        # Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件
        pingTimeout: 60000
        # Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔
        pingInterval: 25000
        # 设置HTTP交互最大内容长度
        maxHttpContentLength: 1048576
        # 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器
        maxFramePayloadLength: 1048576
    

    我说了我是类中直接写的,然后在boot项目的启动类中加入启动代码:

        @Bean
        public SocketIOServer socketIOServer() {
            com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
                    //这里注意,这不能写localhost。
            config.setHostname("192.168.0.11");
            config.setPort(9090);
            config.setAuthorizationListener(new AuthorizationListener() {// 类似过滤器
                @Override
                public boolean isAuthorized(HandshakeData data) {
                    //可以有逻辑,我这里没写
                    return true;
                }
            });
            final SocketIOServer server = new SocketIOServer(config);
            return server;
        }
    
        @Bean
        public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
            return new SpringAnnotationScanner(socketServer);
        }
    

    最后附上一个前端测试页面(我也是在网上嫖的,都忘了是哪个帖子找到的了,在此感谢大佬):

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
      <title>websocket-java-socketio</title>
      <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
    </head>
    <body>
    <h1>Socket.io Test</h1>
    <div><p id="status">Waiting for input</p></div>
    <div><p id="message">hello world!</p></div>
    <button id="connect" onClick='connect()'/>Connect</button>
    <button id="disconnect" onClick='disconnect()'>Disconnect</button>
    <button id="send" onClick='send()'/>Send Message</button>
    </body>
    
    <script type="text/javascript">
    
      /**
       * 前端js的 socket.emit("事件名","参数数据")方法,是触发后端自定义消息事件的时候使用的,
       * 前端js的 socket.on("事件名",匿名函数(服务器向客户端发送的数据))为监听服务器端的事件
       **/
      var socket = io.connect("http://192.168.0.11:9090?params=123");
      var firstconnect = true;
    
      function connect() {
        if(firstconnect) {
    
          //socket.on('reconnect', function(){ status_update("Reconnected to Server"); });
          //socket.on('reconnecting', function( nextRetry ){ status_update("Reconnecting in "
          //+ nextRetry + " seconds"); });
          //socket.on('reconnect_failed', function(){ message("Reconnect Failed"); });
          //firstconnect = false;
        } else {
          socket.socket.reconnect();
        }
      }
    
      //监听服务器连接事件
      socket.on('connect', function(){ status_update("Connected to Server"); });
      //监听服务器关闭服务事件
      socket.on('disconnect', function(){ status_update("Disconnected from Server"); });
      //监听服务器端发送消息事件
      socket.on('update', function(data) {
        message(data)
        //console.log("服务器发送的消息是:"+data);
      });
    
      //断开连接
      function disconnect() {
        socket.disconnect();
      }
    
      function message(data) {
        document.getElementById('message').innerHTML = "Server says: " + data;
      }
    
      function status_update(txt){
        document.getElementById('status').innerHTML = txt;
      }
    
      function esc(msg){
        return msg.replace(/</g, '<').replace(/>/g, '>');
      }
      //点击发送消息触发
      function send() {
        console.log("点击了发送消息,开始向服务器发送消息")
        var msg = "我很好的,是的.";
        socket.emit('messageevent', {msgContent: msg});
      };
    </script>
    </html>
    

    这篇笔记就到这里,如果稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利,生活健健康康!

    相关文章

      网友评论

        本文标题:spring boot 整合netty-socketio

        本文链接:https://www.haomeiwen.com/subject/pbydyhtx.html