TCP 粘包和拆包及解決方案
TCP是面向連接的,面向流的,提供高可靠性服務(wù)。收發(fā)兩端(客戶端和服務(wù)器端)都要有一一成對的socket,因此,發(fā)送端為了將多個發(fā)給接收端的包,更有效的發(fā)給對方,使用了優(yōu)化方法(Nagle算法),將多次間隔較小且數(shù)據(jù)量小的數(shù)據(jù),合并成一個大的數(shù)據(jù)塊,然后進行封包。這樣做雖然提高了效率,但是接收端就難于分辨出完整的數(shù)據(jù)包了,因為面向流的通信是無消息保護邊界的。
由于TCP無消息保護邊界, 需要在接收端處理消息邊界問題,也就是我們所說的粘包、拆包問題。

假設(shè)客戶端分別發(fā)送了兩個數(shù)據(jù)包D1和D2給服務(wù)端,由于服務(wù)端一次讀取到字節(jié)數(shù)是不確定的,故可能存在以下四種情況:
服務(wù)端分兩次讀取到了兩個獨立的數(shù)據(jù)包,分別是D1和D2,沒有粘包和拆包
服務(wù)端一次接受到了兩個數(shù)據(jù)包,D1和D2粘合在一起,稱之為TCP粘包
服務(wù)端分兩次讀取到了數(shù)據(jù)包,第一次讀取到了完整的D1包和D2包的部分內(nèi)容,第二次讀取到了D2包的剩余內(nèi)容,這稱之為TCP拆包
服務(wù)端分兩次讀取到了數(shù)據(jù)包,第一次讀取到了D1包的部分內(nèi)容D1_1,第二次讀取到了D1包的剩余部分內(nèi)容D1_2和完整的D2包。
在編寫Netty 程序時,如果沒有做處理,就會發(fā)生粘包和拆包的問題.
1)使用自定義協(xié)議 + 編解碼器 來解決
2)關(guān)鍵就是要解決 服務(wù)器端每次讀取數(shù)據(jù)長度的問題, 這個問題解決,就不會出現(xiàn)服務(wù)器多讀或少讀數(shù)據(jù)的問題,從而避免的TCP 粘包、拆包 。
public class MessageProtocol {
private int len; // 關(guān)鍵
private byte[] content;
public int getLen() {
return len;
}
public void setLen(int len) {
this.len = len;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
}