最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Netty中最簡(jiǎn)單的粘包解析方法分享

 更新時(shí)間:2023年05月16日 14:55:52   作者:寧軒  
黏包 是指網(wǎng)絡(luò)上有多條數(shù)據(jù)發(fā)送給服務(wù)端, 但是由于某種原因這些數(shù)據(jù)在被接受的時(shí)候進(jìn)行了重新組合,本文分享了一種最簡(jiǎn)單的黏包解析方法, 非常適用于初初初級(jí)選手

前言

黏包 是指網(wǎng)絡(luò)上有多條數(shù)據(jù)發(fā)送給服務(wù)端, 但是由于某種原因這些數(shù)據(jù)在被接受的時(shí)候進(jìn)行了重新組合, 這就是黏包, 本篇文章用來(lái)演示一種最簡(jiǎn)單的黏包解析方法, 適用于初初初級(jí)選手

正常來(lái)講客戶端發(fā)送給服務(wù)端的消息, 都是存在專門的通訊協(xié)議的, 為了避免黏包現(xiàn)象, 我們通常有幾種方式去制定相應(yīng)的規(guī)則: 消息長(zhǎng)度固定, 特定分隔符, 消息長(zhǎng)度固定+特定分隔符

本文是采用了 特定分隔符 的方式, 每條數(shù)據(jù)包都以 \n 結(jié)尾

例如以下三條原始數(shù)據(jù)數(shù)據(jù):

hell\n
ningxuan\n
thanks\n

變成了以下兩個(gè):

hello\nningxuan\nth
anks\n

這就是黏包

黏包產(chǎn)生的原因

socket 網(wǎng)絡(luò)編程中, TCPUDP 分別是面向連接和非面相連接的. 但是他們都存在產(chǎn)生黏包問(wèn)題嗎?

本文不會(huì)對(duì) tcp 和 udp 進(jìn)行詳細(xì)的講解, 感興趣的可以自行百度或者掘金

tcp

先說(shuō)結(jié)論: tcp 會(huì)產(chǎn)生黏包問(wèn)題

由于 tcp 協(xié)議本身的機(jī)制(面向連接的可靠性協(xié)議-三次握手機(jī)制) 客戶端與服務(wù)端會(huì)維持一個(gè)連接(Channel), 數(shù)據(jù)在連接不斷開的情況下, 可以將多個(gè)數(shù)據(jù)包持續(xù)不斷的發(fā)送到服務(wù)器上.

但是如果發(fā)送的網(wǎng)絡(luò)數(shù)據(jù)包太小, tcp就會(huì)啟用Nagle算法對(duì)多個(gè)數(shù)據(jù)包進(jìn)行合并再發(fā)送到服務(wù)器上. 這種情況下服務(wù)器在接收到消息的時(shí)候無(wú)法區(qū)分哪些數(shù)據(jù)包是分開的, 所以產(chǎn)生了黏包

還有一種可能是: 服務(wù)器在接收到數(shù)據(jù)之后, 將數(shù)據(jù)放入到緩沖區(qū)中, 如果消息沒(méi)有被及時(shí)的從緩沖區(qū)取走, 下次在取數(shù)據(jù)的時(shí)候就會(huì)出現(xiàn)一次取到多個(gè)數(shù)據(jù)包的情況, 造成黏包現(xiàn)象

tcp三次握手:

  • 客戶端服務(wù)端發(fā)送建立通道請(qǐng)求
  • 服務(wù)端客戶端發(fā)送允許客戶端建立一個(gè)單向的數(shù)據(jù)通道; 服務(wù)端向客戶端發(fā)送建立通道請(qǐng)求
  • 客戶端服務(wù)端發(fā)送允許服務(wù)端建立一個(gè)單向的數(shù)據(jù)通道

此時(shí)數(shù)據(jù)通道是雙向的, 允許客戶端、服務(wù)端互相發(fā)送消息

Nagle算法:

  • 如果包長(zhǎng)度達(dá)到 MSS, 則允許發(fā)送
  • 如果該包中含有 FIN, 則允許發(fā)送
  • 設(shè)置了 TCP_NODELAY 選項(xiàng), 若所有發(fā)出去的小數(shù)據(jù)包(長(zhǎng)度小于 MSS )均被確認(rèn), 則允許發(fā)送
  • 若上述條件均未滿足, 但發(fā)送了超時(shí)(一般為 200ms ), 則立即發(fā)送

udp

upd 不存在黏包問(wèn)題

udp本身是無(wú)連接的不可靠傳輸協(xié)議, 不會(huì)對(duì)數(shù)據(jù)包進(jìn)行合并發(fā)送, 也就沒(méi)有Nagle算法, 不會(huì)存在數(shù)據(jù)合并的情況, 每一個(gè)數(shù)據(jù)包都是完整的, 所以不存在黏包現(xiàn)象

最簡(jiǎn)單的黏包解析

黏包解析也很簡(jiǎn)單:

  • 遍歷當(dāng)前的 ByteBuffer 緩沖區(qū)
  • 判斷元素為 '\n' 的下標(biāo)
  • 生成新的 ByteBuffer 緩沖區(qū)
  • 將起始下標(biāo)到標(biāo)記下標(biāo)的字符寫到新的緩沖區(qū)

具體代碼如下所示:

public class ByteBufferTest {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(32);
        buffer.put("hello\nningxuan\nth".getBytes());
        split(buffer);
        buffer.put("anks\n".getBytes());
        split(buffer);
    }

    private static void split(ByteBuffer buffer){
        // 將 buffer 切換為 讀模式
        buffer.flip();
        // 根據(jù) buffer 當(dāng)前的長(zhǎng)度進(jìn)行遍歷
        for (int i = 0; i < buffer.limit(); i++) {
            // 判斷當(dāng)前下標(biāo)元素是不是數(shù)據(jù)包切割符 \n
            if (buffer.get(i) == '\n'){ // 注意這個(gè)時(shí)候 buffer 的 position 屬性一直為 0
                // 計(jì)算當(dāng)前數(shù)據(jù)包長(zhǎng)度
                int length = i + 1 - buffer.position();
                // 根據(jù)當(dāng)前數(shù)據(jù)包長(zhǎng)度, 動(dòng)態(tài)生成新的 緩沖區(qū)
                ByteBuffer target = ByteBuffer.allocate(length);
                for (int j = 0; j < length; j++) {
                    target.put(buffer.get());   // 注意這個(gè)時(shí)候 buffer 的 position 屬性在 ++
                }
                // 打印 target 當(dāng)前的元素和屬性
                ByteBufferUtils.selectAll(target);
            }
        }
        buffer.compact();
    }
}

到此這篇關(guān)于Netty中最簡(jiǎn)單的粘包解析方法分享的文章就介紹到這了,更多相關(guān)粘包解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)合并兩個(gè)已經(jīng)排序的列表實(shí)例代碼

    java實(shí)現(xiàn)合并兩個(gè)已經(jīng)排序的列表實(shí)例代碼

    這篇文章主要介紹了java實(shí)現(xiàn)合并兩個(gè)已經(jīng)排序的列表實(shí)例代碼,有需要的朋友可以參考一下
    2013-12-12
  • Java讓泛型實(shí)例化的方法

    Java讓泛型實(shí)例化的方法

    這篇文章主要介紹了Java讓泛型實(shí)例化的方法,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java線程安全狀態(tài)專題解析

    Java線程安全狀態(tài)專題解析

    線程安全是多線程編程時(shí)的計(jì)算機(jī)程序代碼中的一個(gè)概念。在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會(huì)通過(guò)同步機(jī)制保證各個(gè)線程都可以正常且正確的執(zhí)行,不會(huì)出現(xiàn)數(shù)據(jù)污染等意外情況
    2022-03-03
  • solr在java中的使用實(shí)例代碼

    solr在java中的使用實(shí)例代碼

    本篇文章主要介紹了solr在java中的使用實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • Mybatis中一條SQL使用兩個(gè)foreach的問(wèn)題及解決

    Mybatis中一條SQL使用兩個(gè)foreach的問(wèn)題及解決

    這篇文章主要介紹了Mybatis中一條SQL使用兩個(gè)foreach的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java 17 更新后的 strictfp 關(guān)鍵字

    Java 17 更新后的 strictfp 關(guān)鍵字

    strictfp 可能是最沒(méi)有存在感的關(guān)鍵字了,很多人寫了多年 Java 甚至都不知道它的存在,strictfp,字面意思就是嚴(yán)格的浮點(diǎn)型。這玩意兒居然還有個(gè)關(guān)鍵字,可見其地位還是很高的。下面文章小編就帶大家詳細(xì)介紹其關(guān)鍵字,需要的朋友可以參考一下
    2021-09-09
  • springboot集成kafka消費(fèi)手動(dòng)啟動(dòng)停止操作

    springboot集成kafka消費(fèi)手動(dòng)啟動(dòng)停止操作

    這篇文章主要介紹了springboot集成kafka消費(fèi)手動(dòng)啟動(dòng)停止操作,本文給大家介紹項(xiàng)目場(chǎng)景及解決分析,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • Java數(shù)組添加元素的兩種方法

    Java數(shù)組添加元素的兩種方法

    這篇文章主要介紹了Java數(shù)組添加元素的兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友跟著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 16 個(gè)有用的的Java工具類(小結(jié))

    16 個(gè)有用的的Java工具類(小結(jié))

    這篇文章主要介紹了16 個(gè)有用的的Java工具類,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Spring MVC Interceptor 實(shí)現(xiàn)性能監(jiān)控的功能代碼

    Spring MVC Interceptor 實(shí)現(xiàn)性能監(jiān)控的功能代碼

    本篇文章主要介紹了Spring MVC Interceptor 實(shí)現(xiàn)性能監(jiān)控的功能代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09

最新評(píng)論

濉溪县| 钟祥市| 城步| 田林县| 兰西县| 正宁县| 仁怀市| 华阴市| 辽宁省| 丹棱县| 锡林郭勒盟| 北流市| 竹山县| 运城市| 犍为县| 论坛| 宜城市| 康平县| 东山县| 文成县| 奉节县| 蓬安县| 堆龙德庆县| 福鼎市| 米泉市| 绵阳市| 武乡县| 涞源县| 乌鲁木齐市| 青川县| 武冈市| 米泉市| 新津县| 清丰县| 石阡县| 延津县| 闵行区| 常山县| 拜城县| 黄梅县| 日照市|