国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

日常記錄-SpringBoot整合netty-socketio

這篇具有很好參考價(jià)值的文章主要介紹了日常記錄-SpringBoot整合netty-socketio。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

這次整合借鑒了以下博主的智慧

websocket和socketio的區(qū)別

socket.io.js最簡(jiǎn)版單頁HTML測(cè)試工具

Netty-SocketIO多路復(fù)用

springboot學(xué)習(xí)(四十三) springboot使用netty-socketio實(shí)現(xiàn)消息推送

SpringBoot集成SocketIO

一、準(zhǔn)備工作

1、maven依賴

socketio的核心依賴就只有這個(gè)

<!-- netty-socketio: 仿`node.js`實(shí)現(xiàn)的socket.io服務(wù)端 -->
<dependency>
   <groupId>com.corundumstudio.socketio</groupId>
   <artifactId>netty-socketio</artifactId>
   <version>1.7.19</version>
</dependency>

2、socketIO的yml配置

netty-socketio,技術(shù)積累,spring boot,后端,java

#自定義socketio配置,你可以直接硬編碼,看個(gè)人喜好
socketio:
  # socketio請(qǐng)求地址
  host: 127.0.0.1
  # socketio端口
  port: 9999
  # 設(shè)置最大每幀處理數(shù)據(jù)的長度,防止他人利用大數(shù)據(jù)來攻擊服務(wù)器
  maxFramePayloadLength: 1048576
  # 設(shè)置http交互最大內(nèi)容長度
  maxHttpContentLength: 1048576
  # socket連接數(shù)大小(如只監(jiān)聽一個(gè)端口boss線程組為1即可)
  bossCount: 1
  # 連接數(shù)大小
  workCount: 100
  # 允許客戶請(qǐng)求
  allowCustomRequests: true
  # 協(xié)議升級(jí)超時(shí)時(shí)間(毫秒),默認(rèn)10秒。HTTP握手升級(jí)為ws協(xié)議超時(shí)時(shí)間
  upgradeTimeout: 1000000
  # Ping消息超時(shí)時(shí)間(毫秒),默認(rèn)60秒,這個(gè)時(shí)間間隔內(nèi)沒有接收到心跳消息就會(huì)發(fā)送超時(shí)事件
  pingTimeout: 6000000
  # Ping消息間隔(毫秒),默認(rèn)25秒??蛻舳讼蚍?wù)器發(fā)送一條心跳消息間隔
  pingInterval: 25000
  # 命名空間,多個(gè)以逗號(hào)分隔,
  namespaces: /test,/socketIO
  #namespaces: /socketIO

3、socketIO的config代碼

package com.gzgs.socketio.common.config;

import com.corundumstudio.socketio.SocketConfig;
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;

import java.util.Arrays;
import java.util.Optional;

@Configuration
public class SocketIOConfig {

    @Value("${socketio.host}")
    private String host;

    @Value("${socketio.port}")
    private Integer port;

    @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;

    @Value("${socketio.namespaces}")
    private String[] namespaces;

    @Bean
    public SocketIOServer socketIOServer() {
        SocketConfig socketConfig = new SocketConfig();
        socketConfig.setTcpNoDelay(true);
        socketConfig.setSoLinger(0);
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setSocketConfig(socketConfig);
        config.setHostname(host);
        config.setPort(port);
        config.setBossThreads(bossCount);
        config.setWorkerThreads(workCount);
        config.setAllowCustomRequests(allowCustomRequests);
        config.setUpgradeTimeout(upgradeTimeout);
        config.setPingTimeout(pingTimeout);
        config.setPingInterval(pingInterval);

        //服務(wù)端
        final SocketIOServer server = new SocketIOServer(config);

        //添加命名空間(如果你不需要命名空間,下面的代碼可以去掉)
        Optional.ofNullable(namespaces).ifPresent(nss ->
                Arrays.stream(nss).forEach(server::addNamespace));


        return server;
    }

    //這個(gè)對(duì)象是用來掃描socketio的注解,比如 @OnConnect、@OnEvent
    @Bean
    public SpringAnnotationScanner springAnnotationScanner() {

        return new SpringAnnotationScanner(socketIOServer());
    }
}


4、SocketIOServer啟動(dòng)或關(guān)閉

我在啟動(dòng)類里面定義了啟動(dòng)或者關(guān)閉SocketIOServer

package com.gzgs.socketio;

import com.corundumstudio.socketio.SocketIOServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class SocketioServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SocketioServerApplication.class, args);
    }

}

@Component
@Slf4j
class SocketIOServerRunner implements CommandLineRunner, DisposableBean {

    @Autowired
    private SocketIOServer socketIOServer;

    @Override
    public void run(String... args) throws Exception {
        socketIOServer.start();
        log.info("SocketIOServer==============================啟動(dòng)成功");
    }


    @Override
    public void destroy() throws Exception {
        //如果用kill -9  這個(gè)監(jiān)聽是沒用的,有可能會(huì)導(dǎo)致你服務(wù)kill掉了,但是socket服務(wù)沒有kill掉
        socketIOServer.stop();
        log.info("SocketIOServer==============================關(guān)閉成功");
    }
}

netty-socketio,技術(shù)積累,spring boot,后端,java

springboot整合socketIO的工作已經(jīng)完成了

5、項(xiàng)目目錄結(jié)構(gòu)

參考下即可,核心是如何配置以及如何啟動(dòng)/關(guān)閉SocketIO

netty-socketio,技術(shù)積累,spring boot,后端,java

二、客戶端和服務(wù)端建立連接

1、服務(wù)端

1.1 用戶緩存信息ClientCache

package com.gzgs.socketio.common.cache;

import com.corundumstudio.socketio.SocketIOClient;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 這是存儲(chǔ)用戶的緩存信息
 */
@Component
public class ClientCache {

    //用于存儲(chǔ)用戶的socket緩存信息
    private static ConcurrentHashMap<String, HashMap<UUID, SocketIOClient>> concurrentHashMap = new ConcurrentHashMap<>();


    //保存用戶信息
    public void saveClient(String userId,UUID sessionId,SocketIOClient socketIOClient){
        HashMap<UUID, SocketIOClient> sessionIdClientCache = concurrentHashMap.get(userId);
        if(sessionIdClientCache == null){
            sessionIdClientCache = new HashMap<>();
        }
        sessionIdClientCache.put(sessionId,socketIOClient);
        concurrentHashMap.put(userId,sessionIdClientCache);
    }


    //獲取用戶信息
    public HashMap<UUID,SocketIOClient> getUserClient(String userId){
        return concurrentHashMap.get(userId);
    }


    //根據(jù)用戶id和session刪除用戶某個(gè)session信息
    public void deleteSessionClientByUserId(String userId,UUID sessionId){
        concurrentHashMap.get(userId).remove(sessionId);
    }



    //刪除用戶緩存信息
    public void deleteUserCacheByUserId(String userId){
        concurrentHashMap.remove(userId);
    }
}


1.2 SocketIOServerHandler

用于監(jiān)聽客戶端的建立連接請(qǐng)求和關(guān)閉連接請(qǐng)求

package com.gzgs.socketio.common.handler;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;

import com.gzgs.socketio.common.cache.ClientCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;


@Slf4j
@Component
public class SocketIOServerHandler {

    @Autowired
    private ClientCache clientCache;

    /**
     * 建立連接
     * @param client 客戶端的SocketIO
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {

        //因?yàn)槲叶x用戶的參數(shù)為userId,你也可以定義其他名稱 客戶端請(qǐng)求 http://localhost:9999?userId=12345
        
         //下面兩種是加了命名空間的,他會(huì)請(qǐng)求對(duì)應(yīng)命名空間的方法(就類似你進(jìn)了不同的房間玩游戲)
        //因?yàn)槲叶x用戶的參數(shù)為userId,你也可以定義其他名稱 客戶端請(qǐng)求 http://localhost:9999/test?userId=12345
        //因?yàn)槲叶x用戶的參數(shù)為userId,你也可以定義其他名稱 客戶端請(qǐng)求 http://localhost:9999/SocketIO?userId=12345
        String userId = client.getHandshakeData().getSingleUrlParam("userId");

        //同一個(gè)頁面sessionid一樣的
        UUID sessionId = client.getSessionId();

        //保存用戶的信息在緩存里面
        clientCache.saveClient(userId,sessionId,client);

        log.info("SocketIOServerHandler-用戶id:{},sessionId:{},建立連接成功",userId,sessionId);


    }

    /**
     * 關(guān)閉連接
     * @param client 客戶端的SocketIO
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client){

        //因?yàn)槲叶x用戶的參數(shù)為userId,你也可以定義其他名稱
        String userId = client.getHandshakeData().getSingleUrlParam("userId");

        //sessionId,頁面唯一標(biāo)識(shí)
        UUID sessionId = client.getSessionId();

        //clientCache.deleteUserCacheByUserId(userId);
        //只會(huì)刪除用戶某個(gè)頁面會(huì)話的緩存,不會(huì)刪除該用戶不同會(huì)話的緩存,比如:用戶同時(shí)打開了谷歌和QQ瀏覽器,當(dāng)你關(guān)閉谷歌時(shí)候,只會(huì)刪除該用戶谷歌的緩存會(huì)話
        clientCache.deleteSessionClientByUserId(userId,sessionId);

        log.info("SocketIOServerHandler-用戶id:{},sessionId:{},關(guān)閉連接成功",userId,sessionId);
    }





}

2、客戶端

直接復(fù)制建立html文件,在瀏覽器打開就可以使用了

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>SocketIO客戶端測(cè)試環(huán)境</title>
    <base>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/socket.io/2.1.1/socket.io.js"></script>
    <style>
        body {
            padding: 20px;
        }
        #console {
            height: 450px;
            overflow: auto;
        }
        .connect-msg {
            color: green;
        }
        .disconnect-msg {
            color: red;
        }
    </style>
</head>

<body>
<h1>客戶端測(cè)試環(huán)境</h1>
<hr style="height:1px;border:none;border-top:1px solid black;" />

<div style="width: 700px; float: left">
<h3>SocketClient建立連接</h3>
<div style="border: 1px;">

    <label>socketio服務(wù)端地址:</label>
    <!--

      http://localhost 服務(wù)端ip
                  9999 服務(wù)端socket端口(服務(wù)端提供)
                test或socketIO 命名空間(可自定義)如果不定義命名空間,默認(rèn)是/     比如:http://localhost:9999?userId=12345
                userId 用戶id參數(shù)(可自定義)

       ps:因?yàn)槲叶x了命名空間/test和/socketIO,所以我這里也可以用
          http://localhost:9999/test?userId=12345
          http://localhost:9999/socketIO?userId=12345
         這里我用http://localhost:9999?userId=12345建立連接,因?yàn)檫@里還不涉及到請(qǐng)求不同命名空間的方法
      -->
    <input type="text" id="url" value="http://localhost:9999?userId=12345" style="width: 500px;">
    <br>
    <br>
    <button id="connect" style="width: 100px;">建立連接</button>
    <button id="disconnect" style="width: 100px;">斷開連接</button>


</div>

<hr style="height:1px;border:none;border-top:1px solid black;" />

<h3>SocketClient發(fā)送消息</h3>
<div style="border: 1px;">
    <label>socketEvent名稱:</label><input type="text" id="socketEvent" value="getUserRooms">
    <br><br>
    <textarea  id="content" maxlength="1000" cols="40" rows="5" placeholder="請(qǐng)輸入內(nèi)容"></textarea>
    <button id="send" style="width: 100px;">發(fā)送消息</button>
</div>

<hr style="height:1px;border:none;border-top:1px solid black;" />

</div>
<div style="float: left;margin-left: 50px;">
    <h3>SocketIO互動(dòng)消息</h3>
    <button id="clean" style="width: 100px;">清理輸出</button>
    <div id="console" class="well"></div>
</div>


</body>

<script type="text/javascript">
    var socket ;
    var errorCount = 0;
    var isConnected = false;
    var maxError = 5;

    //連接
    function connect(url) {

        //var opts = {
        //    query: 'userId='+userId
        //};
        //socket = io.connect(url, opts);

        socket = io.connect(url);

        //socket.nsp = "/socketIO";//定義命名空間

        console.log(socket)

        //監(jiān)聽本次連接回調(diào)函數(shù)
        socket.on('connect', function () {
            isConnected =true;
            console.log("連接成功");
            serverOutput('<span class="connect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>連接成功</span>');
            errorCount=0;
        });
        //監(jiān)聽消息
        socket.on('message', function (data) {
            output('<span class="connect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>' + data + ' </span>');
            console.log(data);
        });

        //監(jiān)聽斷開
        socket.on('disconnect', function () {
            isConnected =false;
            console.log("連接斷開");
            serverOutput('<span class="disconnect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>' + '已下線! </span>');
        });
        //監(jiān)聽斷開錯(cuò)誤
        socket.on('connect_error', function(data){
            serverOutput('<span class="disconnect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>;' + '連接錯(cuò)誤-'+data+' </span>');
            errorCount++;
            if(errorCount>=maxError){
                socket.disconnect();
            }
        });
        //監(jiān)聽連接超時(shí)
        socket.on('connect_timeout', function(data){
            serverOutput('<span class="disconnect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>' + '連接超時(shí)-'+data+' </span>');
            errorCount++;
            if(errorCount>=maxError){
                socket.disconnect();
            }
        });
        //監(jiān)聽錯(cuò)誤
        socket.on('error', function(data){
            serverOutput('<span class="disconnect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>' + '系統(tǒng)錯(cuò)誤-'+data+' </span>');
            errorCount++;
            if(errorCount>=maxError){
                socket.disconnect();
            }
        });

        /*socket.on('ack', function(data){

            console.log("ack:"+data)
            var str = '消息發(fā)送失敗';
            if(data==1){
                str = '消息發(fā)送成功';
            }
            serverOutput('<span class="connect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>' + str+' </span>');

        });*/
    }

    function output(message) {
        var element = $("<div>" + " " + message + "</div>");
        $('#console').prepend(element);
    }

    function serverOutput(message) {
        var element = $("<div>" + message + "</div>");
        $('#console').prepend(element);
    }

    //連接
    $("#connect").click(function(){
        if(!isConnected){
            var url =  $("#url").val();
            connect(url);
        }else {
            serverOutput('<span class="disconnect-msg"><font color="blue">'+getNowTime()+'&nbsp;</font>' + '已經(jīng)成功建立連接,不要重復(fù)建立?。?! </span>');
        }
    })


    //斷開連接
    $("#disconnect").click(function(){
        if(isConnected){
            socket.disconnect();
        }
    })

    //發(fā)送消息
    $("#send").click(function(){
        var socketEvent =  $("#socketEvent").val();//自定義的事件名稱
        var content  = $("#content").val();//發(fā)送的內(nèi)容
        socket.emit(socketEvent,content,function(data1,data2){
            console.log("ack1:"+data1);
            console.log("ack2:"+data2);
        });
    })

    //清理消息
    $("#clean").click(function(){
        $('#console').html("");
    })

    function getNowTime(){
        var date=new Date();
        var year=date.getFullYear(); //獲取當(dāng)前年份
        var mon=date.getMonth()+1; //獲取當(dāng)前月份
        var da=date.getDate(); //獲取當(dāng)前日
        var h=date.getHours(); //獲取小時(shí)
        var m=date.getMinutes(); //獲取分鐘
        var s=date.getSeconds(); //獲取秒
        var ms=date.getMilliseconds();
        var d=document.getElementById('Date');
        var date =year+'/'+mon+'/'+da+' '+h+':'+m+':'+s+':'+ms;
        return date;
    }
</script>
</html>

html效果如下:
netty-socketio,技術(shù)積累,spring boot,后端,java

3、簡(jiǎn)單的演示

自己點(diǎn)擊建立連接和斷開連接按鈕測(cè)試玩下
ps:http://localhost:9999?userId=12345是沒有命名空間的請(qǐng)求
netty-socketio,技術(shù)積累,spring boot,后端,java
netty-socketio,技術(shù)積累,spring boot,后端,java
netty-socketio,技術(shù)積累,spring boot,后端,java
netty-socketio,技術(shù)積累,spring boot,后端,java

三、廣播

1、SocketIO基礎(chǔ)概念圖

SocketIO、namespace(命名空間)、room(房間)的關(guān)系如下:
netty-socketio,技術(shù)積累,spring boot,后端,java
SocketIO廣播是以namespace或者room為維度的,具體如下:

如果不定義namespace,默認(rèn)是/
如果定義了namespace,沒有定義room,房間默認(rèn)的名字和namespace一樣。

2、定義namespace

netty-socketio,技術(shù)積累,spring boot,后端,java

你也可以這樣定義
server.addNamespace(“/test”);
server.addNamespace(“/socketIO”);

3、創(chuàng)建namespace所屬的Handler

3.1 自定義Handler

package com.gzgs.socketio.common.handler;


import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.fasterxml.jackson.core.JsonProcessingException;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;


@Slf4j
@Component
public class TestHandler {


    //測(cè)試使用
    @OnEvent("testHandler")
    public void testHandler(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {

        log.info("MyTestHandler:{}",data);

        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("MyTestHandler",data);
        }

    }

}

package com.gzgs.socketio.common.handler;


import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;

import com.corundumstudio.socketio.annotation.OnEvent;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;




@Slf4j
@Component
public class SocketIOHandler  {

    //測(cè)試使用
    @OnEvent("socketIOHandler")
    public void testHandler(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {

        log.info("SocketIOHandler:{}",data);

        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("SocketIOHandler",data);
        }

    }

}

netty-socketio,技術(shù)積累,spring boot,后端,java

3.2 監(jiān)聽自定義Handler

在啟動(dòng)類的SocketIO監(jiān)聽里面加入監(jiān)聽
netty-socketio,技術(shù)積累,spring boot,后端,java

package com.gzgs.socketio;

import com.corundumstudio.socketio.SocketIOServer;
import com.gzgs.socketio.common.handler.SocketIOHandler;
import com.gzgs.socketio.common.handler.TestHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class SocketioServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SocketioServerApplication.class, args);
    }

}

@Component
@Slf4j
class SocketIOServerRunner implements CommandLineRunner, DisposableBean {

    @Autowired
    private SocketIOServer socketIOServer;

    @Autowired
    private TestHandler testHandler;

    @Autowired
    private SocketIOHandler socketIOHandler;

    @Override
    public void run(String... args) throws Exception {

        //namespace分別交給各自的Handler監(jiān)聽,這樣就可以隔離,只有客戶端指定namespace,才能訪問對(duì)應(yīng)Handler。
        //比如:http://localhost:9999/test?userId=12345
        socketIOServer.getNamespace("/test").addListeners(testHandler);
        socketIOServer.getNamespace("/socketIO").addListeners(socketIOHandler);
        socketIOServer.start();
        log.info("SocketIOServer==============================啟動(dòng)成功");
    }


    @Override
    public void destroy() throws Exception {
        socketIOServer.stop();
        log.info("SocketIOServer==============================關(guān)閉成功");
    }
}

3.3演示

3.3.1 正確演示

netty-socketio,技術(shù)積累,spring boot,后端,java
netty-socketio,技術(shù)積累,spring boot,后端,java

3.3.1 錯(cuò)誤演示

netty-socketio,技術(shù)積累,spring boot,后端,java

四、常用方法

其他的一些測(cè)試我寫在下面的代碼上,自己去測(cè)試才能更好的理解文章來源地址http://www.zghlxwxcb.cn/news/detail-690801.html

1、加入房間

    //加入房間
    @OnEvent("joinRoom")
    public void joinRooms(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {

        client.joinRoom(data);

        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("加入房間","成功");
        }

    }

2、離開房間

    //離開房間
    @OnEvent("leaveRoom")
    public void leaveRoom(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {

        client.leaveRoom(data);

        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("離開房間","成功");
        }

    }

3、獲取用戶所有房間

    //獲取該用戶所有房間
    @OnEvent("getUserRooms")
    public void getUserRooms(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {

        String userId = client.getHandshakeData().getSingleUrlParam("userId");

        Set<String> allRooms = client.getAllRooms();

        for (String room:allRooms){
            System.out.println("房間名稱:"+room);
        }

        log.info("服務(wù)器收到消息,客戶端用戶id:{} | 客戶發(fā)送的消息:{} | 是否需要返回給客戶端內(nèi)容:{} ",userId,data,ackRequest.isAckRequested());


        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("你好","哈哈哈");
        }


    }

4、發(fā)送消息給指定的房間

   @OnEvent("sendRoomMessage")
    public void sendRoomMessage(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {


        String userId = client.getHandshakeData().getSingleUrlParam("userId");


        Set<String> allRooms = client.getAllRooms();

        for (String room:allRooms){
            log.info("房間:{}",room);
            //發(fā)送給指定空間名稱以及房間的人,并且排除不發(fā)給自己
            socketIoServer.getNamespace("/socketIO").getRoomOperations(room).sendEvent("message",client, data);

            //發(fā)送給指定空間名稱以及房間的人,包括自己
            //socketIoServer.getNamespace("/socketIO").getRoomOperations(room).sendEvent("message", data);;
        }



        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("發(fā)送消息到指定的房間","成功");
        }

    }

5、廣播消息給指定的Namespace下所有客戶端

//廣播消息給指定的Namespace下所有客戶端
    @OnEvent("sendNamespaceMessage")
    public void sendNamespaceMessage(SocketIOClient client, String data, AckRequest ackRequest) throws JsonProcessingException {


        socketIoServer.getNamespace("/socketIO").getBroadcastOperations().sendEvent("message",client, data);;


        if(ackRequest.isAckRequested()){
            //返回給客戶端,說我接收到了
            ackRequest.sendAckData("發(fā)送消息到指定的房間","成功");
        }

    }

6、點(diǎn)對(duì)點(diǎn)發(fā)送

    //點(diǎn)對(duì)點(diǎn)
    public void sendMessageOne(String userId) throws JsonProcessingException {


        HashMap<UUID, SocketIOClient> userClient = clientCache.getUserClient(userId);

        for (UUID sessionId : userClient.keySet()) {
            socketIoServer.getNamespace("/socketIO").getClient(sessionId).sendEvent("message", "這是點(diǎn)對(duì)點(diǎn)發(fā)送");
        }

    }

到了這里,關(guān)于日常記錄-SpringBoot整合netty-socketio的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • SpringBoot整合Netty+Websocket實(shí)現(xiàn)消息推送

    ? ? ? ?Netty是一個(gè)高性能、異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用于快速開發(fā)可維護(hù)的高性能協(xié)議服務(wù)器和客戶端。以下是Netty的主要優(yōu)勢(shì): 高性能 :Netty基于NIO(非阻塞IO)模型,采用事件驅(qū)動(dòng)的設(shè)計(jì),具有高性能的特點(diǎn)。它通過零拷貝技術(shù)、內(nèi)存池化技術(shù)等手段,進(jìn)一步提高

    2024年01月20日
    瀏覽(21)
  • Springboot整合Netty實(shí)現(xiàn)RPC服務(wù)器

    Springboot整合Netty實(shí)現(xiàn)RPC服務(wù)器

    try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(boss, worker) .childHandler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new IdleStateHandler(0, 0, 60)); pipeline.addLast(new JsonDecoder()); pipeline.addLast(new JsonEnco

    2024年04月09日
    瀏覽(25)
  • netty學(xué)習(xí)(3):SpringBoot整合netty實(shí)現(xiàn)多個(gè)客戶端與服務(wù)器通信

    netty學(xué)習(xí)(3):SpringBoot整合netty實(shí)現(xiàn)多個(gè)客戶端與服務(wù)器通信

    創(chuàng)建一個(gè)SpringBoot工程,然后創(chuàng)建三個(gè)子模塊 整體工程目錄:一個(gè)server服務(wù)(netty服務(wù)器),兩個(gè)client服務(wù)(netty客戶端) pom文件引入netty依賴,springboot依賴 NettySpringBootApplication NettyServiceHandler SocketInitializer NettyServer NettyStartListener application.yml Client1 NettyClientHandler SocketInitializ

    2024年02月11日
    瀏覽(56)
  • Springboot中整合netty啟動(dòng)后,項(xiàng)目無法正常啟動(dòng)?

    Springboot中整合netty啟動(dòng)后,項(xiàng)目無法正常啟動(dòng)?

    ? 1.現(xiàn)象描述 netty等一般放在程序啟動(dòng)后再啟動(dòng),多以下面方式啟動(dòng): 如果在 Order 后面還有其它模塊被啟動(dòng),那么其它模塊就會(huì)被阻塞。 2.原因分析 主線程啟動(dòng)netty后,netty會(huì)將主線程阻塞。因此,需要采用異步方式或使用線程池來啟動(dòng)netty。 3.解決辦法 添加異步注解@Async

    2024年02月13日
    瀏覽(23)
  • 記錄一次springboot+netty+websocket報(bào)錯(cuò)的問題

    報(bào)錯(cuò)內(nèi)容 io.netty.handler.codec.htttp.websocketx.textwebsocketframe can not be cast to io.netty.handler.codec.http.FullHttpRequest; 核心問題 springboot項(xiàng)目設(shè)定了項(xiàng)目訪問前綴,/project/ 而我只給websocket設(shè)定了單獨(dú)的訪問路徑 pipeline.addLast(new WebSocketServerProtocolHandler(“/msg”)); 前臺(tái)初始化websocket的路徑是

    2024年02月15日
    瀏覽(20)
  • SpringBoot項(xiàng)目整合WebSocket+netty實(shí)現(xiàn)前后端雙向通信(同時(shí)支持前端webSocket和socket協(xié)議哦)

    SpringBoot項(xiàng)目整合WebSocket+netty實(shí)現(xiàn)前后端雙向通信(同時(shí)支持前端webSocket和socket協(xié)議哦)

    目錄 ? 前言 技術(shù)棧 功能展示 一、springboot項(xiàng)目添加netty依賴 二、netty服務(wù)端 三、netty客戶端 四、測(cè)試 五、代碼倉庫地址 ??專屬小彩蛋:前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到網(wǎng)站(前言 - 床長人工智能教程

    2024年02月12日
    瀏覽(21)
  • SSM學(xué)習(xí)記錄9:SpringBoot整合SSM(注解方式)

    SSM學(xué)習(xí)記錄9:SpringBoot整合SSM(注解方式)

    啟動(dòng)SpringBootDemoApplication↓ springBoot項(xiàng)目內(nèi)含tomcat服務(wù)器,無需手動(dòng)配置↓ 測(cè)試結(jié)果↓ 上下圖來自黑馬程序員的視頻教程,點(diǎn)擊查看教程 配置文件yml與yaml語法↓ 配置文件數(shù)據(jù)讀取方式(3種)↓ 配置文件: 讀取方式: 若自定義方式出現(xiàn)警告↓ Test加載的是同級(jí)目錄下的類,

    2024年02月09日
    瀏覽(48)
  • Java SpringBoot整合elasticsearch 7.17相關(guān)問題記錄

    Java SpringBoot整合elasticsearch 7.17相關(guān)問題記錄

    話不多說直接上代碼,首先關(guān)注點(diǎn)Springboot相關(guān)ES相關(guān)的版本對(duì)應(yīng) 找到對(duì)應(yīng)的版本號(hào),我這里對(duì)應(yīng)7.17.1 對(duì)應(yīng)的springboot版本 2.3.* 即可 上圖為Springboot相關(guān)依賴 ES 創(chuàng)建索引以及映射相關(guān)(首先映射分詞要保持環(huán)境中Es下的分詞器安裝正確) //創(chuàng)建索引 對(duì)應(yīng)的增刪改查 //增加 文檔

    2024年02月11日
    瀏覽(24)
  • SpringBoot中整合ElasticSearch快速入門以及踩坑記錄

    SpringBoot中整合ElasticSearch快速入門以及踩坑記錄

    若依前后端分離版手把手教你本地搭建環(huán)境并運(yùn)行項(xiàng)目: 若依前后端分離版手把手教你本地搭建環(huán)境并運(yùn)行項(xiàng)目_本地運(yùn)行若依前后端分離-CSDN博客 參考上面搭建項(xiàng)目。 Elasticsearch 是java開發(fā)的,基于 Lucene 的搜索引擎。它提供了一個(gè)分布式多用戶能力的全文搜索引擎,基于R

    2024年01月17日
    瀏覽(20)
  • 三步實(shí)現(xiàn)SpringBoot全局日志記錄,整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏

    三步實(shí)現(xiàn)SpringBoot全局日志記錄,整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏

    ?? 注重版權(quán),轉(zhuǎn)載請(qǐng)注明原作者和原文鏈接 小袁博客:https://boke.open-yuan.com/ 小袁博客后臺(tái):https://boke.open-yuan.com/back-manager/ 更多項(xiàng)目內(nèi)容關(guān)注小紅書??OpenYuan開袁 http://xhslink.com/I9zNaC 有需求可以在小袁博客首頁加我微信或者QQ 建表 POJO實(shí)體 Mapper接口 自定義注解 案例: 攔截

    2024年03月08日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包