如何理解TCP協議是無邊界的,以及粘包?

2022-08-23 13:57:16 字數 2374 閱讀 7318

時間版本修改

2023年4月2日

初稿乙個典型的協議頭設計如下:

字段意義

包頭標識_uint8[2]

協議版本號_uint8

當前版本號

clienttype_uint8

客戶端型別(pc,安卓等)

clientversion_uint16

client版本

versiontype_uint8

client版本型別(區分簡繁體等)

userid_uint32

登入使用者id(使用者id)

包型別標誌_uint8

(應答or推送)

serialno_uint32

命令序列號,每傳送乙個命令後加1

cmd_uint16

協議號(區分上層業務)

bodylength_uint32

協議包體長度(本文重點)

reserved

任意byte保留位元組(保留當然不能太長羅)

void cmywintcpsocket::onreceive(int nerrorcode)

//記錄本次套接字被啟用的時間

m_usocketactivetime = ::gettickcount();

dword nbytes = 0;

if (!ioctl(fionread, &nbytes) || nbytes == 0) //fionread返回套接字上排隊的第乙個資料報大小

//此時套接字中可獲取的資料有nbytes個位元組

//開始讀取資料

char *preceivebuffer = new char[nbytes]; //有多少讀多少,一次性讀完

int nread = casyncsocketex::receive(preceivebuffer, nbytes); //nread是實際讀取到的資料

if (nread <= 0) //出現異常,需要退出

int ncurrentoffset = 0; //記錄讀取本次的套接字資料的offset(偏移量)

int nleftsize = nread; //本次套接字返回的資料,剩下的未讀取的位元組數

char *poffsetbuffer = preceivebuffer;

std::vectorvecrecvpacks; //tagrecvpack表示乙個收到的應用層的包,從成員變數offset來判斷當前獲取的位元組數

do //判斷上次呼叫onreceive的資料是否已經讀取完頭部,

if (m_recvpack.uheadoffset < nheaderlen)

m_recvpack.ubodytotal = nbodylength;

if (m_recvpack.ubodytotal == 0) //乙個空包,以前的邏輯是直接拋棄的,現在空包也要

//包體過大,應該是資料錯亂了,剩下的包已經不知道怎麼解析了,只能斷開

else if (m_recvpack.ubodytotal > tcp_protocol_packet_max_length)

//-----------2. 頭部讀完,開始做準備或者容錯之類的工作-----------//

//-----------3. 建立好乾淨的包體,用以儲存包體資料-----------//

if (m_recvpack.ubodytotal > 0)

//-----------3. 建立好乾淨的包體,用以儲存包體資料-----------//}}

//開始讀取包體

else if (m_recvpack.pheadbuffer && m_recvpack.uheadoffset == nheaderlen)

if (m_recvpack.ubodyoffset == m_recvpack.ubodytotal && m_recvpack.pbodybuffer != null) //資料讀取完成

//---4.根據協議頭帶上的包體長度,直接解析包體,如果套接字buffer不夠長,要先存起來,等待下次onreceive呼叫時再粘包---//

}else

} while (nleftsize > 0);

//還回資料

mf_delete1d(preceivebuffer);

//本次解析出來的包,每乙個依次往上層丟擲**

auto uconnectordersession = m_uconnectordersession;

for (auto it : vecrecvpacks)

if (uconnectordersession != m_uconnectordersession)

if (it.ubodytotal == 0)

else

}}

TCP的粘包問題以及資料的無邊界性

上節我們講到了socket緩衝區和資料的傳遞過程,可以看到資料的接收和傳送是無關的,read recv 函式不管資料傳送了多少次,都會盡可能多的接收資料。也就是說,read recv 和 write send 的執行次數可能不同。例如,write send 重複執行三次,每次都傳送字串 abc 那麼...

TCP協議 HTTPS協議的理解

tcp tcp是一種可靠的傳輸協議,為什麼說它可靠呢,因為它有 三次握手 為什麼握三次手就可靠了,握兩次或者一次會怎樣?hi,我可以跟你拉小手手嗎?ok啊,那你現在方便跟我牽嗎?伸出手 好的,我已經抓住你的手了 https是加了安全驗證的http協議。可以這麼說,當你跟某個遠端的小夥伴通過網路傳輸資...

TCP協議是如何確保可靠傳輸的?

關於 tcp協議如何確保可靠傳輸 這個問題,網上的資料參差不齊。近期開始在圖書館讀一些教材,帶著問題讀了以下書目的關於tcp的章節,總結記錄了下來。因而以上3點,可靠傳輸的重擔交予到了tcp之上。為了實現可靠傳輸的目的,tcp使用4個解決方案 面向連線的傳輸機制 超時重傳控制 可變滑動視窗流量控制 ...