網路層是五層結構中的第三層,它的作用就是提供端到端的(主機之間)的通訊;而運輸層屬於第四層,它的作用是提供程序間的通訊。應用層則是最頂層,作用是提供為使用者提供與網路打交道的介面
應用層與運輸層之間通過套接字進行資料傳遞資料,套接字是運輸層與應用層的乙個中間媒介,位於兩層之間。運輸層接收到資料後,將它交付到正確的套接字中,應用層程序從相應的套接字中獲取資料;反之應用層將資料交付到套接字,運輸層從套接字中收集資料。而網路層接受其他主機傳送的資料,去除首部資訊後交給運輸層,由運輸層定向到套接字;反之運輸層也將從套接字中收集的資料封裝後,交給網路層向下傳遞。
通過模擬來理解這兩個概念:假設兩個家庭a和b,各有10名家庭成員。假設這兩個家庭的每乙個成員,在每個星期都要給另乙個家庭的10名成員各寫一封信,所以a家庭每星期都有100封信送到b家庭,b家庭亦是如此。a家庭和b家庭各選出了乙個負責人來處理這件事,假設a家庭的負責人是李明,而b家庭的負責人是韓梅梅,這兩個人每個星期需要幹兩件事:
收集每個家庭成員寫的信,並將它交給郵差,由郵差將信交到另乙個家庭中
郵差將信寄到家來時,負責人統一接收,並根據信上的收件人姓名,將信交給指定的家庭成員;
多路復用的過程就好比負責人要辦的事情1,而多路分解就好比事情2。下面兩個名次的解釋:
多路復用:在資料的傳送端,傳輸層收集各個套接字中需要傳送的資料,將它們封裝上首部資訊(之後用於分解),交給網路層
多路分解:在資料的接收端,傳輸層接收到網路層的報文後,並將它交付到正確的套接字上
家庭成員就好比套接字,而這兩個負責人就好比主機中的運輸層,郵差可以理解為網路層。負責人將寄來的資訊發給家庭成員的過程,類似於運輸層將資料報分發給指定的套接字;而郵差從乙個家庭到另乙個家庭的過程也可以模擬為網路層主機之間的通訊。
那這兩個過程具體如何工作呢?每個程序可以由多個套接字,運輸層如何知道要將資料交付給哪乙個套接字呢?這裡我們需要明確復用/分解的要求:
1.每個套接字都有唯一標識
2.每乙個傳遞到運輸層的報文段,都包含一些特殊字段,來指明它交付到的套接字;
對於每乙個套接字,都能被分配乙個的埠號。所以,上述要求2中所說的特殊字段就是源埠號字段(對於tcp和udp,這個還有一些其他特殊字段)。所以我們知道運輸層如何實現分解服務了:當乙個報文段到達運輸層時,運輸層檢測報文段中的埠號,根據埠號,將其定向到指定的套接字中,然後資料將通過套接字即可進入套接字對應的程序。
上面只是講解了一下這兩個概念的一般形式,但是在具體的實現中要稍微複雜一些,不同協議所使用的套接字也有所區別,下面我們來看看udp
協議中的多路分解與多路復用。
我們知道,udp
是乙個面向無連線,不可靠的運輸層協議,它盡最大努力傳輸資料,但是不保證資料是否到達,或者是否按順序到達,它要做的僅僅是將資料發出,至於發出後如何,它不會在意。
當程序需要傳送udp
資料報時,首先要建立乙個udp套接字,然後應用層通過這個udp
套接字將資料傳遞到運輸層,運輸層為資料加上源埠號以及目的埠號,封裝成資料報後交給網路層,網路層再為資料報封裝上源ip以及目的ip。由於udp
協議僅僅只是將資料發出,所以對於udp
報文來說,最重要的就是目的位址的所在。可能正是因為這個原因,乙個udp
套接字的標識就是目的ip+目的埠號。因此對於多個不同的udp
資料報,只要它們的目的ip
+埠號相同,就算源位址不同,也會在目的主機中被定向到同乙個udp
套接字中,被同乙個程序所接收。目的ip決定了資料報將要傳送到哪台主機,而目的埠號為運輸層的的分解提供了標識。
這裡可能就會有些疑問了,既然這樣,那udp
報文為什麼需要包含源ip
+源埠號呢(ip
在網路層被封裝)?這是因為udp
是無連線的,當接收到乙個udp
報文時,可能想要回送乙個報文,這時候不知道源在何處將無法實現。所以當需要向源主機回覆報文時,只需提取udp
報文中的源ip
和源埠號,然後將它們作為目的ip
+目的埠號即可實現。
上面只是講解了一下這兩個概念的一般形式,但是在具體的實現中要稍微複雜一些,不同協議所使用的套接字也有所區別,下面我們來看看udp
協議中的多路分解與多路復用。
我們知道,udp
是乙個面向無連線,不可靠的運輸層協議,它盡最大努力傳輸資料,但是不保證資料是否到達,或者是否按順序到達,它要做的僅僅是將資料發出,至於發出後如何,它不會在意。
當程序需要傳送udp
資料報時,首先要建立乙個udp套接字,然後應用層通過這個udp
套接字將資料傳遞到運輸層,運輸層為資料加上源埠號以及目的埠號,封裝成資料報後交給網路層,網路層再為資料報封裝上源ip以及目的ip。由於udp
協議僅僅只是將資料發出,所以對於udp
報文來說,最重要的就是目的位址的所在。可能正是因為這個原因,乙個udp
套接字的標識就是目的ip+目的埠號。因此對於多個不同的udp
資料報,只要它們的目的ip
+埠號相同,就算源位址不同,也會在目的主機中被定向到同乙個udp
套接字中,被同乙個程序所接收。目的ip決定了資料報將要傳送到哪台主機,而目的埠號為運輸層的的分解提供了標識。
這裡可能就會有些疑問了,既然這樣,那udp
報文為什麼需要包含源ip
+源埠號呢(ip
在網路層被封裝)?這是因為udp
是無連線的,當接收到乙個udp
報文時,可能想要回送乙個報文,這時候不知道源在何處將無法實現。所以當需要向源主機回覆報文時,只需提取udp
報文中的源ip
和源埠號,然後將它們作為目的ip
+目的埠號即可實現。
既然有無連線的實現,自然就有連線的實現。運輸層乃至整個計算機網路最著名的協議——tcp
協議,就是乙個面向連線的協議。tcp
是乙個面向連線,可靠的運輸層協議。既然面向連線,那它就需要關注兩個方面:源位址和目的位址,因為tcp
的傳輸,需要兩邊協作完成。正因為tcp
的特性,導致tcp
的套接字和udp
也有所區別。tcp
套接字的標識是乙個四元組,即源ip+源埠+目的ip+目的埠(udp
是目的ip
+目的埠)。我們通過乙個例項來講解tcp
的多路復用/分解過程。
大部分人使用最多的應用層協議應該就是http
協議,而它就是基於tcp
協議實現的,當我們在瀏覽器中請求乙個頁面時,將經歷以下過程:
web
伺服器監聽80
埠,等待客戶端的連線;
使用者在瀏覽器輸入乙個url
,回車後,瀏覽器程序建立乙個套接字,此套接字由伺服器ip
,伺服器80
埠,本地ip
,本地程序埠,四部分標識;
瀏覽器程序將資料通過此套接字從應用層傳入運輸層,運輸層為tcp
報文加上首部(包括源埠和目的埠)後,交給網路層,網路層為其加上網路層首部(包括源ip
和目的ip
)傳輸傳輸到web
伺服器;
web
伺服器的接收到此資料報後,檢測到資料報請求的是埠80
,於是檢測80
埠正在執行,且允許連線,則建立乙個新的套接字,此套接字由伺服器ip
,伺服器80
埠,源ip
,源埠,這四部分標識;
此後到達的web
伺服器的資料報,若以上四部分完全相等,則將進入此套接字中;
既然tcp
套接字是由源ip+源埠+目的ip+目的埠四部分標識,不難想到,我們無法在同一臺主機上,依靠同乙個埠,向伺服器的某個乙個埠建立兩個tcp
連線,因為這樣將無法區分兩個連線。以下通過j**a
進行測試:
public static void main(string args) throws ioexception
以上**執行時丟擲異常,提示位址已經被使用,但是修改第二個socket
物件的本地埠後,異常消失,驗證了上面的結論。
計算機網路——多路復用與多路分解 - 特務依昂 - (cnblogs.com)
Linux IO多路復用
一.select 函式 include include include int select int n,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout fd clr int fd,fd set set f...
I O多路復用
一 五種i o模型 1 阻塞i o模型 最流行的i o模型是阻塞i o模型,預設情形下,所有套介面都是阻塞的。我們以資料報套介面為例來講解此模型 我們使用udp而不是tcp作為例子的原因在於就udp而言,資料準備好讀取的概念比較簡單 要麼整個資料報已經收到,要麼還沒有。然而對於tcp來說,諸如套介面...
Linux C Socket多路復用
1.迴圈伺服器 udp伺服器 udp迴圈伺服器的實現非常簡單 udp伺服器每次從套接字上讀取乙個客戶端的請求,處理,然後將結果返回給客戶機.可以用下面的演算法來實現.socket bind while 1 因為udp是非面向連線的,沒有乙個客戶端可以老是佔住服務端.只要處理過程不是死迴圈,伺服器對於...