作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!
我們已經講解了物理層、串連層和網路層。最開始的串連層協議種類繁多(Ethernet、Wifi、ARP等等)。到了網路層,我們只剩下一個IP協議(IPv4和IPv6是替代關係)。進入到傳輸層(transport layer),協議的種類又開始繁多起來(比如TCP、UDP、SCTP等)。這就好像下面的大樹,根部(串連層)分叉很多,然後統一到一個樹榦(網路層),到了樹冠(傳輸層)部分又開始開始分叉,而每個樹枝上長出更多的樹葉(應用程式層)。我們在網路層已經看到,通過樹榦的統一,我們實現了一個覆蓋全球的互連網絡(Internet)。然而,我們可能出於不同的目的利用這張“網”,隨之使用的方式也有所區分。不同的傳輸層協議(以及更多的應用程式層協議)正是我們使用“網”的不同方式的體現。
網路分層的“藝術”觀點
傳輸層最重要的協議為TCP協議和UDP協議。這兩者使用“網”的方式走了兩個極端。兩個協議的對比非常有趣。TCP協議複雜,但傳輸可靠。UDP協議簡單,但傳輸不可靠。其他的各個傳輸層協議在某種程度上都是這兩個協議的折中。我們先來看傳輸層協議中比較簡單的UDP協議。我們將參考許多之前文章的內容(協議森林01, 03, 05)。
UDP協議簡介
UDP(User Datagram Protocol)傳輸與IP傳輸非常類似。你可以將UDP協議看作IP協議暴露在傳輸層的一個介面。UDP協議同樣以資料包(datagram)的方式傳輸,它的傳輸方式也是"Best Effort"的,所以UDP協議也是不可靠的(unreliable)。那麼,我們為什麼不直接使用IP協議而要額外增加一個UDP協議呢? 一個重要的原因是IP協議中並沒有連接埠(port)的概念。IP協議進行的是IP地址到IP地址的傳輸,這意味者兩台電腦之間的對話。但每台電腦中需要有多個通訊通道,並將多個通訊通道分配給不同的進程使用(關於進程,可以參考Linux進程基礎)。一個連接埠就代表了這樣的一個通訊通道。正如我們在郵局和郵差中提到的收信人的概念一樣。UDP協議實現了連接埠,從而讓資料包可以在送到IP地址的基礎上,進一步可以送到某個連接埠。
UDP:依然不是那麼“可靠”
儘管UDP協議非常簡單,但它的產生晚於更加複雜的TCP協議。早期的網路開發人員開發出IP協議和TCP協議分別位於網路層和傳輸層,所有的通訊都要先經過TCP封裝,再經過IP封裝(應用程式層->TCP->IP)。開發人員將TCP/IP視為相互合作的套裝。但很快,網路開發人員發現,IP協議的功能和TCP協議的功能是相互獨立的。對於一些簡單的通訊,我們只需要“Best Effort”式的IP傳輸就可以了,而不需要TCP協議複雜的建立串連的方式(特別是在早期網路環境中,如果過多的建立TCP串連,會造成很大的網路負擔,而UDP協議可以相對快速的處理這些簡單通訊)。UDP協議隨之被開發出來,作為IP協議在傳輸層的"傀儡"。這樣,網路通訊可以通過應用程式層->UDP->IP的封裝方式,繞過TCP協議。由於UDP協議本身異常簡單,實際上只為IP傳輸起到了橋樑的作用。我們將在TCP協議的講解中看到更多TCP協議和UDP協議的對比。
IP和他的傀儡UDP
UDP的資料包同樣分為頭部(header)和資料(payload)兩部分。UDP是傳輸層(transport layer)協議,這意味著UDP的資料包需要經過IP協議的封裝(encapsulation),然後通過IP協議傳輸到目的電腦。隨後UDP包在目的電腦拆封,並將資訊送到相應連接埠的緩衝中。
UDP協議的頭部
來自wikipedia
上面的source port和destination port分別為UDP包的出發連接埠和目的地連接埠。Length為整個UDP包的長度。
checksum的演算法與IP協議的header checksum演算法相類似。然而,UDP的checksum所校正的序列包括了整個UDP資料包,以及封裝的IP頭部的一些資訊(主要為出發地IP和目的地IP)。這樣,checksum就可以校正IP:連接埠的正確性了。在IPv4中,checksum可以為0,意味著不使用checksum。IPv6要求必須進行checksum校正。
連接埠與socket
連接埠(port)是伴隨著傳輸層誕生的概念。它可以將網路層的IP通訊分送到各個通訊通道。UDP協議和TCP協議儘管在工作方式上有很大的不同,但它們都建立了從一個連接埠到另一個連接埠的通訊。
IP:連接埠
隨著我們進入傳輸層,我們也可以叫用作業系統中的API,來構建socket。Socket是作業系統提供的一個編程介面,它用來代表某個網路通訊。應用程式通過socket來調用系統核心中處理網路通訊協定的模組,而這些核心模組會負責具體的網路通訊協定的實施。這樣,我們可以讓核心來接收網路通訊協定的細節,而我們只需要提供所要傳輸的內容就可以了,核心會幫我們控制格式,並進一步向底層封裝。因此,在實際應用中,我們並不需要知道具體怎麼構成一個UDP包,而只需要提供相關資訊(比如IP地址,比如連接埠號碼,比如所要傳輸的資訊),作業系統核心會在傳輸之前會根據我們提供的相關資訊構成一個合格的UDP包(以及下層的包和幀)。socket是一個比較大的課題,在協議森林系列中不會過多深入。
(在原始Python伺服器我們討論了如何使用socket建立一個TCP串連,可以作為一個參考)
總結
連接埠是傳輸層帶來的最重要的概念。我們進一步瞭解了UDP協議。如果已經掌握了IP協議,那麼UDP協議就沒有任何困難可言,它只是IP協議暴露在傳輸層上的介面。
歡迎繼續閱讀“協議森林”系列