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

TCP粘包和拆包問題及其解決方法

這篇具有很好參考價值的文章主要介紹了TCP粘包和拆包問題及其解決方法。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

含義:

TCP 傳輸協(xié)議是面向流的,沒有數(shù)據(jù)包界限,也就是說消息無邊界。客戶端向服務端發(fā)送數(shù)據(jù)時,可能將一個完整的報文拆分成多個小報文進行發(fā)送,也可能將多個報文合并成一個大的報文進行發(fā)送。(TCP協(xié)議的底層,并不了解上層業(yè)務的具體定義,它會根據(jù)TCP緩沖區(qū)的實際情況進行包的劃分。在業(yè)務層面認為一個完整的包,可能會被TCP拆分成多個小包進行發(fā)送,也可能把多個小的包封裝成一個大的數(shù)據(jù)包進行發(fā)送,這就是所謂的TCP粘包拆包問題。)。
因此就有了拆包和粘包。 在網(wǎng)絡通信的過程中,每次可以發(fā)送的數(shù)據(jù)包大小是受多種因素限制的,如 MTU 傳輸單元大小、滑動窗口等。
所以如果一次傳輸?shù)木W(wǎng)絡包數(shù)據(jù)大小超過傳輸單元大小,那么我們的數(shù)據(jù)可能會拆分為多個數(shù)據(jù)包發(fā)送出去。 如果每次請求的網(wǎng)絡包數(shù)據(jù)都很小,比如一共請求了 10000 次,TCP 并不會分別發(fā)送 10000 次。 TCP采用的 Nagle(批量發(fā)送,主要用于解決頻繁發(fā)送小數(shù)據(jù)包而帶來的網(wǎng)絡擁塞問題) 算法對此作出了優(yōu)化。

TCP粘包和拆包問題及其解決方法

客戶端發(fā)送了兩個數(shù)據(jù)包P1和P2給服務端,服務端一次讀取到的字節(jié)數(shù)是不確定的,可能存在以下4種情況:

(1)服務端分兩次讀取到了兩個獨立的數(shù)據(jù)包P1和P2,沒有發(fā)送粘包和拆包;
(2)服務端一次讀到

了兩個數(shù)據(jù)包,P1和P2粘在一起,這就是TCP粘包情況;
(3)服務端分兩次讀取到了兩個數(shù)據(jù)包,第一次讀取了完整的P1包和P2包的一部分,第二次讀取到了P2包的剩余部分,這被稱為TCP拆包;
(4)服務端分兩次讀取了兩個數(shù)據(jù)包,第一次讀取了P1包的一部分,第二次讀取到了P1包的剩余部分,這也是TCP拆包;

解決方法:

由于TCP協(xié)議底層無法理解上層的業(yè)務數(shù)據(jù),所以在底層是無法保證數(shù)據(jù)包不被拆分和重組的,所以,這個問題只能通過上層的應用層協(xié)議設計來解決,常見方案如下:

(1)消息定長,發(fā)送方和接收方規(guī)定固定大小的消息長度,例如每個報文大小固定為200字節(jié),如果不夠,空位補空格;(消息定長法使用非常簡單,但是缺點也非常明顯,無法很好設定固定長度的值,如果長度太大會造成字節(jié)浪費,長度太小又會影響消息傳輸,所以在一般情況下消息定長法不會被采用。)
(2)在包圍增加特殊字符進行分割,例如FTP協(xié)議;分隔符的選擇一定要避免和消息體中字符相同,以免沖突。否則可能出現(xiàn)錯誤的消息拆分。比較推薦的做法是將消息進行編碼,例如 base64 編碼,然后可以選擇 64 個編碼字符之外的字符作為特定分隔符。
(3)自定義協(xié)議,將消息分為消息頭和消息體,消息頭中包含消息總長度,這樣服務端就可以知道每個數(shù)據(jù)包的具體長度了,知道了發(fā)送數(shù)據(jù)包的具體邊界后,就可以解決粘包和拆包問題了;

TCP粘包和拆包問題及其解決方法

netty解決粘包拆包問題:

DelimiterBasedFrameDecoder:每個應用層數(shù)據(jù)包,都通過自定義分隔符,進行分割拆分
LineBasedFrameDecoder:每個應用層數(shù)據(jù)包,都以換行符作為分隔符,進行分割拆分。
FixedLengthFrameDecoder:每個應用層數(shù)據(jù)包的拆分都是固定長度大小
LengthFieldBasedFrameDecoder+LengthFieldPrepender:自定義消息長度。?將應用層數(shù)據(jù)包的長度,作為接收端應用層數(shù)據(jù)包的拆分依據(jù)。按照應用層數(shù)據(jù)包的大小,進行拆包。這個拆包器有個要求,應用層協(xié)議包含數(shù)據(jù)包長度。(LengthFieldPrepender:待發(fā)送消息長度寫入到前幾個字節(jié))。

筆者本人自研rpc框架的編解碼自定義協(xié)議:

先讀取消息類型(Requst, Response), 序列化方式(原生, json?加上消息長度:防止粘包, 再根據(jù)長度讀取data.

消息類型(2Byte) 序列化方式 2Byte 消息長度 4Byte
序列化后的Data…. 序列化后的Data… 序列化后的Data….
編碼 
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
        // 寫入消息類型
        if(msg instanceof RPCRequest){
            out.writeShort(MessageType.REQUEST.getCode());
        }
        else if(msg instanceof RPCResponse){
            out.writeShort(MessageType.RESPONSE.getCode());
        }
        // 寫入序列化方式
        out.writeShort(serializer.getType());
        // 得到序列化數(shù)組
        byte[] serialize = serializer.serialize(msg);
        // 寫入長度
        out.writeInt(serialize.length);
        // 寫入序列化字節(jié)數(shù)組
        out.writeBytes(serialize);
    }
解碼
 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 1. 讀取消息類型
        short messageType = in.readShort();
        // 現(xiàn)在還只支持request與response請求
        if(messageType != MessageType.REQUEST.getCode() &&
                messageType != MessageType.RESPONSE.getCode()){
            System.out.println("暫不支持此種數(shù)據(jù)");
            return;
        }
        // 2. 讀取序列化的類型
        short serializerType = in.readShort();
        // 根據(jù)類型得到相應的序列化器
        Serializer serializer = Serializer.getSerializerByCode(serializerType);
        if(serializer == null)throw new RuntimeException("不存在對應的序列化器");
        // 3. 讀取數(shù)據(jù)序列化后的字節(jié)長度
        int length = in.readInt();
        // 4. 讀取序列化數(shù)組
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
        // 用對應的序列化器解碼字節(jié)數(shù)組
        Object deserialize = serializer.deserialize(bytes, messageType);
        out.add(deserialize);
    }

?文章來源地址http://www.zghlxwxcb.cn/news/detail-420710.html

到了這里,關于TCP粘包和拆包問題及其解決方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • 「 計算機網(wǎng)絡 」TCP的粘包拆包問題

    「 計算機網(wǎng)絡 」TCP的粘包拆包問題

    參考鳴謝 大病初愈,一分鐘看懂TCP粘包拆包 雷小帥 TCP 的粘包拆包以及解決方案 一樂說 當我們在進行網(wǎng)絡傳輸時,由于各種原因,數(shù)據(jù)包的發(fā)送和接收可能會出現(xiàn)粘包和拆包的問題。粘包和拆包都是數(shù)據(jù)分組錯誤的情況,其中粘包指的是多個數(shù)據(jù)包被合并成一個,而拆包則

    2024年02月01日
    瀏覽(25)
  • 【計網(wǎng)】一起聊聊TCP的粘包拆包問題吧

    【計網(wǎng)】一起聊聊TCP的粘包拆包問題吧

    在TCP中,粘包和拆包問題是十分常見的,如 基于TCP協(xié)議 的RPC框架、Netty等。 粘包(Packet Stickiness) 指的是在網(wǎng)絡通信中,發(fā)送方連續(xù)發(fā)送的多個小數(shù)據(jù)包被接收方一次性接收的現(xiàn)象。這可能是因為底層傳輸層協(xié)議(如TCP)會將 多個小數(shù)據(jù)包合并成一個大的數(shù)據(jù)塊 進行傳輸,導

    2024年04月12日
    瀏覽(16)
  • TCP的粘包、拆包、解決方案以及Go語言實現(xiàn)

    TCP的粘包、拆包、解決方案以及Go語言實現(xiàn)

    TCP的粘包和拆包問題往往出現(xiàn)在基于TCP協(xié)議的通訊中,比如RPC框架 在使用TCP進行數(shù)據(jù)傳輸時,由于TCP是基于字節(jié)流的協(xié)議,而不是基于消息的協(xié)議,可能會出現(xiàn)粘包(多個消息粘在一起)和拆包(一個消息被拆分成多個部分)的問題。這些問題可能會導致數(shù)據(jù)解析錯誤或數(shù)據(jù)

    2024年02月15日
    瀏覽(27)
  • 粘包/拆包問題一直都存在,只是到TCP就拆不動了。

    粘包/拆包問題一直都存在,只是到TCP就拆不動了。

    OSI open-system-Interconnection TCP/IP 5層協(xié)議棧 應用層和操作系統(tǒng)的邊界是 系統(tǒng)調用 ,對應到網(wǎng)絡編程是socket api TCP/UDP 概況 TCP粘包問題 TCP/IP報頭深思 定義了網(wǎng)絡框架,以層為單位實現(xiàn)協(xié)議,同時控制權逐層傳遞。 OSI實際并沒有落地,TCP/IP 5層協(xié)議棧是目前主流的落地實現(xiàn) 。 TC

    2024年02月03日
    瀏覽(95)
  • 聊聊TCP協(xié)議的粘包、拆包以及http是如何解決的?

    聊聊TCP協(xié)議的粘包、拆包以及http是如何解決的?

    目錄 一、粘包與拆包是什么? 二、粘包與拆包為什么發(fā)生? 三、遇到粘包、拆包怎么辦? 解決方案1:固定數(shù)據(jù)大小 解決方案2:自定義請求協(xié)議 解決方案3:特殊字符結尾 ?四、HTTP如何解決粘包問題的? 4.1、讀取請求行/請求頭、響應行/響應頭 4.2、 怎么讀取body數(shù)據(jù)呢?

    2024年02月11日
    瀏覽(49)
  • C++ Qt TCP協(xié)議,處理粘包、拆包問題,加上數(shù)據(jù)頭來處理

    目錄 前言: 場景: 原因: 解決: 方案2具體細節(jié): 純C++服務端處理如下: Qt客戶端處理如下: ? ? ? ? tcp協(xié)議里面,除了心跳檢測是關于長連接操作的處理,這個在前一篇已經(jīng)提到過了,這一篇將會對tcp本身的一個問題,進行處理:那就是做網(wǎng)絡通信大概率會遇到的問題

    2024年02月04日
    瀏覽(22)
  • Socket TCP/IP協(xié)議數(shù)據(jù)傳輸過程中的粘包和分包問題

    Socket TCP/IP協(xié)議數(shù)據(jù)傳輸過程中的粘包和分包問題

    一:通過圖解法來描述一下分包和粘包,這樣客戶更清晰直觀的了解: 下面對上面的圖進行解釋: 1.正常情況:如果Socket Client 發(fā)送的數(shù)據(jù)包,在Socket Server端也是一個一個完整接收的,那個就不會出現(xiàn)粘包和分包情況,數(shù)據(jù)正常讀取。 2.粘包情況:Socket Client發(fā)送的數(shù)據(jù)包,

    2024年02月12日
    瀏覽(22)
  • 說說 TCP的粘包、拆包

    說說 TCP的粘包、拆包

    拆包和粘包是在socket編程中經(jīng)常出現(xiàn)的情況, 在socket通訊過程中,如果通訊的一端一次性連續(xù)發(fā)送多條數(shù)據(jù)包,tcp協(xié)議會將 多個數(shù)據(jù)包打包 成一個tcp報文發(fā)送出去,這就是所謂的 粘包 。 如果通訊的一端發(fā)送的數(shù)據(jù)包超過一次tcp報文所能傳輸?shù)淖畲笾禃r,就會將 一個數(shù)據(jù)包

    2024年02月09日
    瀏覽(24)
  • Netty-LengthFieldBasedFrameDecoder-解決拆包粘包問題的解碼器

    Netty-LengthFieldBasedFrameDecoder-解決拆包粘包問題的解碼器

    maxFrameLength:指定解碼器所能處理的數(shù)據(jù)包的最大長度,超過該長度則拋出 TooLongFrameException 異常; lengthFieldOffset:指定 長度字段 的起始位置; lengthFieldLength:指定 長度字段 的長度:目前支持1(byte)、2(short)、3(3個byte)、4(int)、8(Long) lengthAdjustment:指定 長度字段 所表示的消息

    2024年02月12日
    瀏覽(21)
  • Netty編解碼器,Netty自定義編解碼器解決粘包拆包問題,Netty編解碼器的執(zhí)行過程詳解

    Netty編解碼器,Netty自定義編解碼器解決粘包拆包問題,Netty編解碼器的執(zhí)行過程詳解

    當Netty發(fā)送或者接收一個消息的時候,就會發(fā)生一次數(shù)據(jù)轉換。入站消息會被解碼(從字節(jié)轉換為另一種格式,比如java對象);出站消息會被編碼成字節(jié)。 Netty 提供一系列實用的編解碼器,他們都實現(xiàn)了 ChannelInboundHadnler 或者 ChannelOutboundHandler 接口。在這些類中,channelRead 方

    2023年04月23日
    瀏覽(32)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領取紅包

二維碼2

領紅包