若是對和程序員有關的計算機網絡知識,和對計算機網絡方面的編程有興趣,歡迎去gitbook(https://rogerzhu.gitbooks.io/-tcp-udp-ip/content/)star個人這一系列文章,雖說如今這種「看不見」的東西真正能在實用中遇到的機會很少,可是我始終以爲不管計算機的語言,熱點方向怎麼變化,做爲一個程序員,不少基本的知識都應該有所瞭解。而當時在網上搜索資料的時候,這方面的資料真的是少的可憐,因此,我有幸前兩年接觸了這方面的知識,我以爲我應該把我知道的記錄下來,雖然寫的不必定很好,可是但願能給須要幫助的人多個參考。個人計劃是用半年時間來寫完這一系列文章,這個標題也是我對太多速成文章的一種態度,好了,廢話再也不多扯了,下面是其中的一節內容,更多內容能夠去gitbook上找到。git
從這一節開始就進入傳輸層的部分了,也是內容最豐富可能更貼近於實際的部分了,不少書籍會從TCP開始介紹傳輸層,我以爲學習應該從簡單的到難的,因此我選擇從UDP先開始,何況是現有UDP協議而且發展至成熟而後再有的TCP。程序員
若是有人問我他想閱讀RFC,也就是我前面提過的互聯網的標準,有啥推薦的着手點。標準這種玩意兒大部分都又枯燥又長,真要看,睡着了是必須的,不看吧,總感受與人談論的時候少了一種老子當年也是參加過啥啥的感受。因此若是真想看看RFC到底都寫些啥,怎麼寫,我十分推薦原始的UDP標準做爲一個開始,UDP的RFC號是768,一共就3頁,完整而又嚴謹的闡述了UDP協議,雖然是英文,全看一遍也就最多30分鐘吧,並且有圖有真相,有文字有引用,做爲一個着手點再合適不過。編程
UDP協議,學名User Datagram Protocol,Datagram這個名詞第一次在網絡中是在1970年,在一個很早期的網路設計CYCLADES中被一個叫Louis Pouzin提出。這個詞是data和telegram的一個組合,而這個CYCLADES是一個保證在可靠傳輸data而不保證可靠傳輸網絡的設計,簡單的來講就是這個網絡設計保證從放到一個端口上傳出去的數據能夠完整無誤的到達另外一端可是不保證一端想要傳輸的數據都能可靠的被放在端口上或者被另外一端取出。這個Louis Pouzin提出這樣一個想法的緣由之一就是他並不喜歡事情搞得很複雜,他認爲沒有必要在一個已經具備可靠傳輸的機制上再疊加一層可靠傳輸的端到端的設計。網絡
從目前看這個想法雖然是有弊端的,可是在當時並無那麼大的網絡負載和網絡架構的時候,這是一種經濟而又行之有效的辦法,因此Datagram這個想法就被IP協議的設計者們所借鑑。架構
就如上一節所描述,Datagram提供的是一種不可靠的協議傳輸,最簡單的不可靠就是從A端的傳輸層發出的數據包不保證B端能接收到,或者按須要收到,B端也無需向A端代表本身是否收到。這有點像之前有一種羣寄廣告的方法,寄廣告的一方並不知道他寄出的地址的人有沒有收到本身寄出去的廣告,而收到廣告更不必向寄出的人代表本身收到與否。tcp
本質上爲何稱UDP爲不可靠呢?由於他並不會保存發送出去的備份,這個特色在UDP中致使會有如下幾個方面的表現:學習
另外UDP也沒有擁塞控制,這個專業名詞到TCP的時候會詳細描述,其實就是當路上流量很大甚至被堵的徹底走不動的時候,UDP協議會無論這些東西,繼續向網絡上發送數據包。這樣會引發不少不良後果,好比丟包,形成網絡整個的崩潰。ui
那麼UDP有這麼多弱點爲何還做爲傳輸層兩巨頭之一被普遍運用呢?由於其長處也很明顯,就是經濟。所謂經濟就是UDP沒有複雜的創建鏈接,重傳重排,擁塞避免(這些名詞後面都會成爲主角)等等,他只管在一端把數據發出去,同等狀況下相對於要作這麼多額外工做的協議確定要快一些且「經濟」一些,那麼有的應用對於數據包短暫丟失,亂序,錯亂都是可以忍受的。最能理解的應用應該是網絡視頻,網絡電話之類的,對於一兩幀的丟失並不會引發用戶的抱怨。固然除了視頻,還有不少協議是創建在UDP之上的,他們中有的已經退出歷史舞臺,有的依然每天都會爲咱們的上網默默的作出你看不到的工做,好比DHCP,DNS。甚至還有因爲其沒有鏈接性的特色不得不使用UDP的場景,就是傳輸層廣播。spa
UDP是工做在IP之上的,是一個應用層到IP的簡單接口,因此UDP整個的數據包是放在IP data部分的(能夠回去再複習一下IP數據包頭格式)。而UDP數據包頭被設計的及其簡單而又有效,整個包頭只有8個字節,分爲四個部分。這裏我要用RFC裏面的原圖了,這裏我不得不說RFC裏的圖是我最佩服的部分之一,各類各樣的圖示都用字符來繪畫出來,有的真的能夠說讓我歎爲觀止。計算機網絡
從低字節到高字節依次是源端口,目的地端口,數據包長度,CRC校驗和。
若是讓我選傳輸層第一關鍵詞,我會選端口,應用層的各類協議的最重要的標識物之一就是傳輸層的端口。爲何在IP地址上還要加上端口這個概念呢?第一個做用是可讓一個主機上的應用層能夠有標識進行IP地址的複用,第二個就是分層思想裏最重要的,每一層都處理每一層的事情,鏈路層看到MAC地址就知道這是鏈路層的數據包,網絡層看到IP地址或者相似的地址就知道本身該幹活了,傳輸層也是一個道理。這樣數據才能沿協議棧不斷的上傳,而每一層也能夠幹本身的事情。
因此相似IP數據包頭有本身和對端的IP地址同樣,在UDP數據包頭中會含有本身的源端口號和對方的端口號。不過因爲UDP是不須要對方返回響應消息的,因此源端口號能夠填0表示不填。一個端口號是16位,因此一個IP地址最大的端口號是65535,可是不少端口號都是預先被保留用作特定的用途,這個在傳輸層雜項中我再稍微詳細的介紹一下。
接下來按照我前面所介紹的記這種數據頭格式的重要部分,就是長度,由於你須要讓對方知道我該讀多少的數據。
接下來的CRC校驗和比較有趣了,IP包頭的效驗和是頭部校驗和,只有頭部的數據會參與計算。而在UDP裏,這個校驗和採用了一個僞頭部的概念。所謂僞頭部就是UDP在計算效驗和的時會把IP頭部的一些信息加入計算,具體的就是以下的信息:
其中包括,源IP地址,目的地IP地址,填充的8位0,協議名(UDP),UDP報文長度,爲何要這麼作呢,標準裏的解釋是經過IP地址能夠確認該數據包是否是發送給本機,經過協議,能夠確認有沒有誤傳。這樣作的好處是很明顯的,一是能夠再一次確認關鍵字段沒有錯誤,而是使用僞首部而不是真正的把這些數據放在UDP數據包裏能夠減小負擔。
可是這個設計違背們一直強調的分層思想,在傳輸層不該該混入網絡層的東西,並且在網絡層的頭數據包CRC中已經讓兩個IP地址參與計算過了,這裏再進行一次校驗,看起來有點多餘。而我對這個問題也一直不知道最深的設計原理是什麼,個人理解是可能在分層思想的時候隱含着雖然每一層都作本身的事情,可是上一層不該該自然相信下一層,在須要的時候他也能夠對下一層的某些關鍵信息再作雙層確認。
對於這個校驗和,由於UDP是不保證可靠性的,在IPv4中是能夠不填的,而以我遇到過的例子來看,大部分是不填的,或者填了對端也不會檢驗的,所謂多一事不如少一事的哲學思惟看來也是通用的。
按照風格,再一次讓咱們來看看現實抓包中的UDP數據包頭是什麼樣子的。
這個圖中能夠看到,UDP是創建在IP紙上的,這裏的源端口號是68,目的地端口號是67,長度329,這裏開啓了checksum可是對端也不會確認計算的。最後一個stream index 是wireshark內部的編號,用來標識UDP,TCP數據流的序號,用中括號括起來的都不是UDP數據包中真正的內容。
好了,UDP就是這麼簡單的一個協議,可是用處倒是很普遍,從下一節開始,就從不一樣的幾個方面來介紹下UDP在每一臺電腦上都會作的幾件事情。