TCP粘包/拆包java
TCP是個"流"協議,所謂流,就是沒有界限沒有分割的一串數據。TCP會根據緩衝區的實際狀況進行包劃分,一個完整的包可能會拆分紅多個包進行發送,也用可能把多個小包封裝成一個大的數據包發送。這就是TCP粘包/拆包。spa
TCP粘包/拆包問題說明code
客戶端要給服務端發送數據,假如爲兩個數據包。ip
可能的狀況以下:get
問題產生的緣由:it
1-應用程序write寫入的字節大小 大於 套接字發送緩衝區大小pip
2-進行MSS大小的TCP分段ast
3-以太網幀的payload大於MTU進行IP分片class
TCP粘包/拆包解決辦法sed
1-定長消息,例如每一個報文長度固定,不夠補空格
2-使用回車換行符分割,在包尾加上分割符,例如Ftp協議
3-消息分割,頭爲長度(消息總長度或消息體長度),一般頭用一個int32表示
4-複雜的應用層協議
Netty對於讀寫半包的的處理
提供多種解碼器用於處理半包,如 LineBasedFrameDecoder、DelimiterBasedFrameDecoder、FixedLengthFrameDecoder、ProtobufVarint32FrameDecoder、ByteToMessageDecoder以及LengthFileldBasedFrameDecoder等等。
下面的例子爲 我在 ProtoBuf中的使用
//decoder //1-讀半包的解碼器 ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4)); //2-進行消息解碼 ch.pipeline().addLast(new ProtobufDecoder(BoxAuthReqProto.AuthRequest.getDefaultInstance())); //encoder ch.pipeline().addLast(new LengthFieldPrepender(4)); ch.pipeline().addLast(new ProtobufEncoder());