TCP套接字--阻塞模式和粘包問題


對於TCP套接字(默認情況下),當使用 write()/send() 發送數據時:

1) 首先會檢查緩沖區,如果緩沖區的可用空間長度小於要發送的數據,那么 write()/send() 會被阻塞(暫停執行),
直到緩沖區中的數據被發送到目標機器,騰出足夠的空間,才喚醒 write()/send() 函數繼續寫入數據。 2) 如果TCP協議正在向網絡發送數據,那么輸出緩沖區會被鎖定,不允許寫入,write()/send() 也會被阻塞,
直到數據發送完畢緩沖區解鎖,write()/send() 才會被喚醒。 3) 如果要寫入的數據大於緩沖區的最大長度,那么將分批寫入。 4) 直到所有數據被寫入緩沖區 write()/send() 才能返回。

當使用 read()/recv() 讀取數據時:

1) 首先會檢查緩沖區,如果緩沖區中有數據,那么就讀取,否則函數會被阻塞,直到網絡上有數據到來。

2) 如果要讀取的數據長度小於緩沖區中的數據長度,那么就不能一次性將緩沖區中的所有數據讀出,
剩余數據將不斷積壓,直到有 read()/recv() 函數再次讀取。 3) 直到讀取到數據后 read()/recv() 函數才會返回,否則就一直被阻塞。 這就是TCP套接字的阻塞模式。所謂阻塞,就是上一步動作沒有完成,下一步動作將暫停,直到上一步動作完成后才能繼續,以保持同步性。

TCP套接字默認情況下是阻塞模式,也是最常用的。當然你也可以更改為非阻塞模式。

TCP粘包問題和數據無界性

上面講到了socket緩沖區和數據的傳遞過程,可以看到數據的接收和發送是無關的,read()/recv() 函數不管數據發送了多少次,
都會盡可能多的接收數據。也就是說,read()/recv() 和 write()/send() 的執行次數可能不同。 例如,write()/send() 重復執行三次,每次都發送字符串"abc",那么目標機器上的 read()/recv() 可能分三次接收,
每次都接收"abc";也可能分兩次接收,第一次接收"abcab",第二次接收"cabc";也可能一次就接收到字符串"abcabcabc"。 假設我們希望客戶端每次發送一位學生的學號,讓服務器端返回該學生的姓名、住址、成績等信息,這時候可能就會出現問題,服務器端不能區分學生的學號。
例如第一次發送
1,第二次發送 3,服務器可能當成 13 來處理,返回的信息顯然是錯誤的。
這就是數據的“粘包”問題,客戶端發送的多個數據包被當做一個數據包接收。
也稱數據的無邊界性,read()/recv() 函數不知道數據包的開始或結束標志(實際上也沒有任何開始或結束標志),
只把它們當做連續的數據流來處理。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM