tcp(transport control protocol,傳輸控制協議)是面向連線的,面向流的,提供高可靠性服務。收發兩端(客戶端和伺服器端)都要有一一成對的socket,因此,傳送端為了將多個發往接收端的包,更有效的發到對方,使用了優化方法(nagle演算法),將多次間隔較小且資料量小的資料,合併成乙個大的資料塊,然後進行封包。這樣,接收端,就難於分辨出來了,必須提供科學的拆包機制。 即面向流的通訊是無訊息保護邊界的。
udp(user datagram protocol,使用者資料報協議)是無連線的,面向訊息的,提供高效率服務。不會使用塊的合併優化演算法,, 由於udp支援的是一對多的模式,所以接收端的skbuff(套接字緩衝區)採用了鏈式結構來記錄每乙個到達的udp包,在每個udp包中就有了訊息頭(****位址,埠等資訊),這樣,對於接收端來說,就容易進行區分處理了。 即面向訊息的通訊是有訊息保護邊界的。
tcp是基於資料流的,於是收發的訊息不能為空,這就需要在客戶端和服務端都新增空訊息的處理機制,防止程式卡住,而udp是基於資料報的,即便是你輸入的是空內容(直接回車),那也不是空訊息,udp協議會幫你封裝上訊息頭。
1.tcp的發包問題
問:tcp 傳送兩次資料,第一次傳送100位元組 ,第二次傳送200位元組, 接包方一次recv( 1000 )會接收到多少?收到是 100,還是200,還是300?
答:tcp 是流協議,所以recv( 1000 ),會收到300。tcp自己處理好了重傳,保證資料報的完整性。
2.udp的發包問題
問:udp 傳送兩次資料,第一次傳送100位元組 ,第二次傳送200位元組, 接包方一次recvfrom( 1000 )會接收到多少?收到是 100,還是200,還是300?
答:udp 是資料報文協議,是以資料報方式,所以每次可以接收100,200,在理想情況下,第一次是無論recvfrom多少都是接收到100。當然,可能由於網路原因,第二個包先到的話,有可能是200了。對可能會由於網路原因亂序,所以可能先收到200,所以自定義的udp協議包頭裡都要加上乙個序列號,標識傳送與收包對應。
3.有分片的情況下如下處理
問:如果mtu是1500,client傳送乙個8000位元組大小的udp包,那麼server端阻塞模式下接包,在不丟包的情況下,recvfrom(9000)是收到1500,還是8000。如果某個ip分片丟失了,recvfrom(9000),又返回什麼呢?
答:根據udp通訊的有界性,在buf足夠大的情況下,接收到的一定是乙個完整的資料報,udp資料在下層的分片和組片問題由ip層來處理,提交到udp傳輸層一定是乙個完整的udp包,那麼recvfrom(9000)將返回8000。如果某個ip分片丟失,udp裡有個crc檢驗,如果包不完整就會丟棄,也不會通知是否接收成功,所以udp是不可靠的傳輸協議,那麼recvfrom(9000)將阻塞。
問:如果mtu是1500,使用udp傳送 2000,那麼recvfrom(2000)是收到1500,還是2000?
答: 還是接收2000,資料分片由ip層處理了,放到udp還是乙個完整的包。接收到的包是由路由路徑上最少的mtu來分片,注意轉到udp已經在是組裝好的(組裝出錯的包會經crc校驗出錯而丟棄),是乙個完整的資料報。
關於TCP黏包問題
最近發現自己對於tcp通訊中的黏包問題還有疑問,查閱資料做下總結。一 tcp黏包問題 tcp黏包問題是因為傳送方把若干資料傳送,接收方收到資料時候黏在一包,從接受緩衝區來看,後一包的資料黏在前一包的尾部。二 黏包出現的原因 tcp黏包問題主要出現在兩個方面 1 傳送方問題 首先tcp會預設使用nag...
044 python TCP 粘包問題的解決
解決粘包問題,目前較為合理的方法就是 為位元組流加上乙個包頭,告訴接收方位元組流的總大小,然後接收方就可以利用while迴圈來接受完所有資料。然後用struck將序列化後的資料打包成多個位元組即可。客戶端 from socket import import struct import os clie...
網路程式設計筆記 3 解決黏包問題
優點 缺點 注意 server端 import socket sk socket.socket sk.bind 127.0.0.1 8080 sk.listen conn,addr sk.accept while true cmd input if cmd q conn.send b q break...