Linux網(wǎng)絡(luò)編程之無連接和面向連接協(xié)議的區(qū)別
網(wǎng)絡(luò)編程中最基本的概念就是面向連接(connection-oriented)和無連接(connectionless)協(xié)議。盡管本質(zhì)上來說,兩者之間的區(qū)別并不難理解,但對(duì)那些剛剛開始進(jìn)行網(wǎng)絡(luò)編程的人來說,卻是個(gè)很容易混淆的問題。這個(gè)問題與上下文有些關(guān)聯(lián):很顯然,如果兩臺(tái)計(jì)算機(jī)要進(jìn)行通信,就必須以某種形式“連接”起來,那“無連接通信”又是什么意思呢?
答案是:面向連接和無連接指的都是協(xié)議。也就是說,這些術(shù)語指的并不是物理介質(zhì)本身,而是用來說明如何在物理介質(zhì)上傳輸數(shù)據(jù)的。面向連接和無連接協(xié)議可以,而且通常也確實(shí)會(huì)共享同一條物理介質(zhì)。
如果兩者的區(qū)別與承載數(shù)據(jù)的物理介質(zhì)無關(guān),又和什么有關(guān)呢?它們的本質(zhì)區(qū)別在于,對(duì)無連接協(xié)議來說,每個(gè)分組的處理都獨(dú)立于所有其他分組,而對(duì)面向連接的協(xié)議來說,協(xié)議實(shí)現(xiàn)則維護(hù)了與后繼分組有關(guān)的狀態(tài)信息。
無連接協(xié)議中的分組被稱為數(shù)據(jù)報(bào)(datagram),每個(gè)分組都是獨(dú)立尋址,并由應(yīng)用程序發(fā)送的。從協(xié)議的角度來看,每個(gè)數(shù)據(jù)報(bào)都是一個(gè)獨(dú)立的實(shí)體,與在兩個(gè)相同的對(duì)等實(shí)體之間傳送的任何其他數(shù)據(jù)報(bào)都沒有關(guān)系,這就意味著協(xié)議很可能是不可靠的。也就是說,網(wǎng)絡(luò)會(huì)盡***努力傳送每一個(gè)數(shù)據(jù)報(bào),但并不保證數(shù)據(jù)報(bào)不丟失、不延遲或者不錯(cuò)序傳輸。
另一方面,面向連接的協(xié)議則維護(hù)了分組之間的狀態(tài),使用這種協(xié)議的應(yīng)用程序通常都會(huì)進(jìn)行長期的對(duì)話。記住這些狀態(tài),協(xié)議就可以提供可靠的傳輸。比如,發(fā)送端可以記住哪些數(shù)據(jù)已經(jīng)發(fā)送出去了但還未被確認(rèn),以及數(shù)據(jù)是什么時(shí)候發(fā)送的。如果在某段時(shí)間間隔內(nèi)沒有收到確認(rèn),發(fā)送端可以重傳數(shù)據(jù)。接收端可以記住已經(jīng)收到了哪些數(shù)據(jù),并將重復(fù)的數(shù)據(jù)丟棄。如果分組不是按序到達(dá)的,接收端可以將其保存下來,直到邏輯上先于它的分組到達(dá)為止。
典型的面向連接協(xié)議有三個(gè)階段。***階段,在對(duì)等實(shí)體間建立連接。接下來是數(shù)據(jù)傳輸階段,在這個(gè)階段中,數(shù)據(jù)在對(duì)等實(shí)體間傳輸。***,當(dāng)對(duì)等實(shí)體完成數(shù)據(jù)傳輸時(shí),連接被拆除。
一種標(biāo)準(zhǔn)的類比是:使用無連接協(xié)議就像寄信,而使用面向連接的協(xié)議就像打電話。
給朋友寄信時(shí),每封信都是一個(gè)獨(dú)立尋址且自包含的實(shí)體。郵局在處理這些信件時(shí)不會(huì)考慮到兩個(gè)通信者之間的任何其他信件。郵局不會(huì)維護(hù)以往通信者的歷史記錄--也就是說,它不會(huì)維護(hù)信件之間的狀態(tài)。郵局也不保證信件不丟失、不延遲、不錯(cuò)序。這種方式就對(duì)應(yīng)于無連接協(xié)議發(fā)送數(shù)據(jù)報(bào)的方式。(用明信片進(jìn)行類比會(huì)更合適一些,因?yàn)閷戝e(cuò)地址的信件會(huì)被退回發(fā)信人,而(和典型的無連接協(xié)議數(shù)據(jù)報(bào)一樣)明信片則不會(huì)。)
現(xiàn)在來看看不是給朋友寄信,而是打電話時(shí)會(huì)發(fā)生些什么事情。
首先,撥朋友的號(hào)碼來發(fā)起呼叫。朋友應(yīng)答,會(huì)說“嗨”之類的話,然后我們回應(yīng):“嗨,Lucy。我是 Mike。”我們和朋友聊一會(huì)兒,然后互說再見并掛機(jī)。這是面向連接協(xié)議中發(fā)生的典型狀況。在連接建立階段,一端與其對(duì)等實(shí)體聯(lián)系,交換初始問候信息,對(duì)會(huì)話中要用到的一些參數(shù)和選項(xiàng)進(jìn)行溝通,然后連接進(jìn)入數(shù)據(jù)傳輸階段。
在電話交談的過程中,兩端用戶都知道他們?cè)诤驼l說話,因此沒必要不停地說“這是 Mike 在跟 Lucy 說話”。也沒必要在每次說話之前都撥一次朋友的電話號(hào)碼——我們的電話已經(jīng)連接起來了。同理,在面向連接協(xié)議的數(shù)據(jù)傳輸階段,也沒必要說明我們自己或?qū)Φ葘?shí)體的地址。連接為我們維護(hù)的狀態(tài)中包含了這些地址。我們只要發(fā)送數(shù)據(jù)就行了,不需要考慮尋址或其他與協(xié)議相關(guān)的問題。
就像用電話交談一樣,連接的任一端完成數(shù)據(jù)的傳輸時(shí),都要通知其對(duì)等實(shí)體。兩端都完成傳輸時(shí),要依次將連接拆除。
既然無連接協(xié)議有這么多的缺點(diǎn),大家可能會(huì)奇怪,為什么還要使用這種協(xié)議呢?我們會(huì)看到,在很多情況下,使用無連接協(xié)議構(gòu)建應(yīng)用程序都是有意義的。比如,使用無連接協(xié)議可以很方便地支持一對(duì)多和多對(duì)一通信,而面向連接協(xié)議通常都需要多個(gè)獨(dú)立的連接才能做到。但更重要的是,無連接協(xié)議是構(gòu)建面向連接協(xié)議的基礎(chǔ)。TCP/IP 是基于一個(gè)4層的協(xié)議棧,如下圖所示:
如圖所示,TCP 和 UDP 都是構(gòu)建在 IP 之上的。因此,IP 是構(gòu)建整個(gè) TCP/IP 協(xié)議族的基礎(chǔ)。但 IP 提供的是一種盡力而為的、不可靠的無連接服務(wù)。它接收來自其上層的分組,將它們封裝在一個(gè) IP 分組中,根據(jù)路由為分組選擇正確的硬件接口,從這個(gè)接口將分組發(fā)送出去。一旦將分組發(fā)送出去了,IP 就不再關(guān)心這個(gè)分組了。和所有無連接協(xié)議一樣,它將分組發(fā)送出去之后就不再記得這個(gè)分組了。
這種簡單性也是 IP 的主要優(yōu)點(diǎn)。因?yàn)樗鼘?duì)底層的物理介質(zhì)沒有作任何假設(shè),所以在任何能夠承載分組的物理鏈路上都可以運(yùn)行 IP。例如,IP 可以運(yùn)行在簡單的串行鏈路、以太網(wǎng)和令牌環(huán) LAN、X.25 和使用 ATM(Asychronous Transfer Mode,異步轉(zhuǎn)移模式)的 WAN、CDPD(Cellular Digital Packet Data,無線蜂窩數(shù)字分組數(shù)據(jù))網(wǎng),以及很多其他網(wǎng)絡(luò)上。盡管這些網(wǎng)絡(luò)技術(shù)之間有很大的差異,但 IP 對(duì)它們一視同仁,除了認(rèn)為它們可以轉(zhuǎn)發(fā)分組之外沒有對(duì)其作任何假設(shè)。這種機(jī)制隱含了很深的意義。IP 可以運(yùn)行在任何能夠承載分組的網(wǎng)絡(luò)上,所以整個(gè) TCP/IP 協(xié)議族也可以。
現(xiàn)在我們來看看 TCP 是怎樣利用這種簡單的無連接服務(wù)來提供可靠的面向連接服務(wù)的。TCP 的分組被稱為段(segment),是放在 IP 數(shù)據(jù)報(bào)中發(fā)送的,因此,根本無法假定這些分組會(huì)抵達(dá)目的地,更不用說保證分組無損壞且以原來的順序到達(dá)了。
為了提供這種可靠性,TCP 向基本的 IP 服務(wù)中添加了三項(xiàng)功能:
首先,它為 TCP 段中的數(shù)據(jù)提供了校驗(yàn)和。這樣有助于確保抵達(dá)目的地的數(shù)據(jù)在傳輸過程中不會(huì)被網(wǎng)絡(luò)損壞。
第二,它為每字節(jié)分配了一個(gè)序列號(hào),這樣,如果數(shù)據(jù)抵達(dá)目的地時(shí)真的錯(cuò)序了,接收端也能夠按照恰當(dāng)?shù)捻樞驅(qū)⑵渲匮b起來。當(dāng)然,TCP 并沒有為每字節(jié)都附加一個(gè)序列號(hào)。實(shí)際上,每個(gè) TCP 段的首部都包含了段中***字節(jié)的序列號(hào)。這樣,就隱含地知道了段中其他字節(jié)的序列號(hào)。
第三,TCP 提供了一種確認(rèn)-重傳機(jī)制,以確保最終每個(gè)段都會(huì)被傳送出去。
另一方面,UDP 為編寫應(yīng)用程序的程序員提供了一種不可靠的無連接服務(wù)。事實(shí)上,UDP 只向底層的 IP 協(xié)議中添加了兩項(xiàng)功能。
首先,它提供了一個(gè)可選的校驗(yàn)和來檢測(cè)數(shù)據(jù)的損壞情況。盡管 IP 也有校驗(yàn)和,但它只對(duì) IP 分組首部進(jìn)行計(jì)算,所以,TCP 和 UDP 也都提供了校驗(yàn)和來保護(hù)它們自己的首部和數(shù)據(jù)。
其次,UDP 向 IP添加的第二項(xiàng)特性就是端口的概念。
回到與電話/寄信的類比中來,我們可以把 TCP 連接中的網(wǎng)絡(luò)地址當(dāng)作一個(gè)辦公室總機(jī)的電話號(hào)碼,把端口號(hào)當(dāng)作辦公室中某臺(tái)正被呼叫的特定電話的分機(jī)號(hào)。同理,可以將UDP網(wǎng)絡(luò)地址當(dāng)作一座公寓樓的地址,并把端口號(hào)當(dāng)作公寓樓大廳中的個(gè)人郵箱。















 
 
 





 
 
 
 