面向報文(UDP)和面向字節(jié)流(TCP)的區(qū)別
面向報文的傳輸方式是應(yīng)用層交給UDP多長的報文,UDP就照樣發(fā)送,即一次發(fā)送一個報文。因此,應(yīng)用程序必須選擇合適大小的報文。若報文太長,則IP層需要分片,降低效率。若太短,會是IP太小。UDP對應(yīng)用層交下來的報文,既不合并,也不拆分,而是保留這些報文的邊界。這也就是說,應(yīng)用層交給UDP多長的報文,UDP就照樣發(fā)送,即一次發(fā)送一個報文。
面向字節(jié)流的話,雖然應(yīng)用程序和TCP的交互是一次一個數(shù)據(jù)塊(大小不等),但TCP把應(yīng)用程序看成是一連串的無結(jié)構(gòu)的字節(jié)流。TCP有一個緩沖,當(dāng)應(yīng)用程序傳送的數(shù)據(jù)塊太長,TCP就可以把它劃分短一些再傳送。如果應(yīng)用程序一次只發(fā)送一個字節(jié),TCP也可以等待積累有足夠多的字節(jié)后再構(gòu)成報文段發(fā)送出去。
下圖是TCP和UDP協(xié)議的一些應(yīng)用。

下圖是TCP和UDP協(xié)議的比較。

這里再詳細(xì)說一下面向連接和面向無連接的區(qū)別:
面向連接舉例:兩個人之間通過電話進(jìn)行通信;
面向無連接舉例:郵政服務(wù),用戶把信函放在郵件中期待郵政處理流程來傳遞郵政包裹。顯然,不可達(dá)代表不可靠。
從程序?qū)崿F(xiàn)的角度來看,可以用下圖來進(jìn)行描述。

從上圖也能清晰的看出,TCP通信需要服務(wù)器端偵聽listen、接收客戶端連接請求accept,等待客戶端connect建立連接后才能進(jìn)行數(shù)據(jù)包的收發(fā)(recv/send)工作。而UDP則服務(wù)器和客戶端的概念不明顯,服務(wù)器端即接收端需要綁定端口,等待客戶端的數(shù)據(jù)的到來。后續(xù)便可以進(jìn)行數(shù)據(jù)的收發(fā)(recvfrom/sendto)工作。
在前面講解UDP時,提到了UDP保留了報文的邊界,下面我們來談?wù)凾CP和UDP中報文的邊界問題。在默認(rèn)的阻塞模式下,TCP無邊界,UDP有邊界。
● 對于TCP協(xié)議,客戶端連續(xù)發(fā)送數(shù)據(jù),只要服務(wù)端的這個函數(shù)的緩沖區(qū)足夠大,會一次性接收過來,即客戶端是分好幾次發(fā)過來,是有邊界的,而服務(wù)端卻一次性接收過來,所以證明是無邊界的;
● 而對于UDP協(xié)議,客戶端連續(xù)發(fā)送數(shù)據(jù),即使服務(wù)端的這個函數(shù)的緩沖區(qū)足夠大,也只會一次一次的接收,發(fā)送多少次接收多少次,即客戶端分幾次發(fā)送過來,服務(wù)端就必須按幾次接收,從而證明,這種UDP的通訊模式是有邊界的。
TCP無邊界,造成對采用TCP協(xié)議發(fā)送的數(shù)據(jù)進(jìn)行接收比較麻煩,在接收的時候易出現(xiàn)粘包,即發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時粘成一包。由于TCP是流協(xié)議,對于一個socket的包,如發(fā)送 10AAAAABBBBB兩次,由于網(wǎng)絡(luò)原因***次又分成兩次發(fā)送, 10AAAAAB和BBBB,如果接包的時候先讀取10(包長度)再讀入后續(xù)數(shù)據(jù),當(dāng)接收得快,發(fā)送的慢時,就會出現(xiàn)先接收了 10AAAAAB,會解釋錯誤 ,再接到BBBB10AAAAABBBBB,也解釋錯誤的情況。這就是TCP的粘包。
在網(wǎng)絡(luò)傳輸應(yīng)用中,通常需要在網(wǎng)絡(luò)協(xié)議之上再自定義一個協(xié)議封裝一下,簡單做法就是在要發(fā)送的數(shù)據(jù)前面再加一個自定義的包頭,包頭中可以包含數(shù)據(jù)長度和其它一些信息,接收的時候先收包頭,再根據(jù)包頭中描述的數(shù)據(jù)長度來接收后面的數(shù)據(jù)。詳細(xì)做法是:先接收包頭,在包頭里指定包體長度來接收。設(shè)置包頭包尾的檢查位( 比如以0xAA開頭,0xCC結(jié)束來檢查一個包是否完整)。對于TCP來說:
1)不存在丟包,錯包,所以不會出現(xiàn)數(shù)據(jù)出錯 ;
2)如果包頭檢測錯誤,即為非法或者請求,直接重置即可。
為了避免粘包現(xiàn)象,可采取以下幾種措施。
一、對于發(fā)送方引起的粘包現(xiàn)象,用戶可通過編程設(shè)置來避免,TCP提供了強(qiáng)制數(shù)據(jù)立即傳送的操作指令push,TCP軟件收到該操作指令后,就立即將本段數(shù)據(jù)發(fā)送出去,而不必等待發(fā)送緩沖區(qū)滿;
二、對于接收方引起的粘包,則可通過優(yōu)化程序設(shè)計、精簡接收進(jìn)程工作量、提高接收進(jìn)程優(yōu)先級等措施,使其及時接收數(shù)據(jù),從而盡量避免出現(xiàn)粘包現(xiàn)象;
三、由接收方控制,將一包數(shù)據(jù)按結(jié)構(gòu)字段,人為控制分多次接收,然后合并,通過這種手段來避免粘包。