目錄
傳輸層
再談端口號
端口號范圍劃分
認識知名端口號
兩個問題
netstat與iostat
pidof
UDP協議
UDP協議格式
UDP協議的特點
面向數據報
UDP的緩沖區
UDP使用注意事項
基于UDP的應用層協議
傳輸層
在學習HTTP等應用層協議時,為了便于理解,可以簡單的認為HTTP協議是將請求和響應直接發送到了網絡當中。但實際應用層需要先將數據交給傳輸層,由傳輸層對數據做進一步處理后再將數據繼續向下進行交付,該過程貫穿整個網絡協議棧,最終才能將數據發送到網絡當中。
傳輸層負責可靠性傳輸,確保數據能夠可靠地傳送到目標地址。為了方便理解,在學習傳輸層協議時也可以簡單的認為傳輸層協議是將數據直接發送到了網絡當中。
再談端口號
端口號的作用
端口號(Port)標識一個主機上進行網絡通信的不同的應用程序。當主機從網絡中獲取到數據后,需要自底向上進行數據的交付,而這個數據最終應該交給上層的哪個應用處理程序,就是由該數據當中的目的端口號來決定的。
從網絡中獲取的數據在進行向上交付時,在傳輸層就會提取出該數據對應的目的端口號,進而確定該數據應該交付給當前主機上的哪一個服務進程。
因此端口號是屬于傳輸層的概念的,在傳輸層協議的報頭當中就會包含與端口相關的字段。
五元組標識一個通信
?在TCP/IP協議中,用“源IP地址”,“源端口號”,“目的IP地址”,“目的端口號”,“協議號”這樣一個五元組來標識一個通信。
比如有多臺客戶端主機同時訪問服務器,這些客戶端主機上可能有一個客戶端進程,也可能有多個客戶端進程,它們都在訪問同一臺服務器。
而這臺服務器就是通過“源IP地址”,“源端口號”,“目的IP地址”,“目的端口號”,“協議號”來識別一個通信的。
- 先提取出數據當中的目的IP地址和目的端口號,確定該數據是發送給當前服務進程的。
- 然后提取出數據當中的協議號,為該數據提供對應類型的服務。
- 最后提取出數據當中的源IP地址和源端口號,將其作為響應數據的目的IP地址和目的端口號,將響應結果發送給對應的客戶端進程。
?
通過netstat
命令可以查看到這樣的五元組信息。?
其中的Local Address表示的就是源IP地址和源端口號,Foreign Address表示的就是目的IP地址和目的端口號,而Proto表示的就是協議類型。
協議號 VS 端口號?
- 協議號是存在于IP報頭當中的,其長度是8位。協議號指明了數據報所攜帶的數據是使用的何種協議,以便讓目的主機的IP層知道應該將該數據交付給傳輸層的哪個協議進行處理。
- 端口號是存在于UDP和TCP報頭當中的,其長度是16位。端口號的作用是唯一標識一臺主機上的某個進程。
- 端口號是存在于UDP和TCP報頭當中的,其長度是16位。端口號的作用是唯一標識一臺主機上的某個進程。
端口號范圍劃分
端口號的長度是16位,因此端口號的范圍是0 ~ 65535:
- 0 ~ 1023:知名端口號。比如HTTP,FTP,SSH等這些廣為使用的應用層協議,它們的端口號都是固定的。
- 1024 ~ 65535:操作系統動態分配的端口號。客戶端程序的端口號就是由操作系統從這個范圍分配的。
認識知名端口號
常見的知名端口號
有些服務器是非常常用的,這些服務器的端口號一般都是固定的:
- ssh服務器,使用22端口。
- ftp服務器,使用21端口。
- telnet服務器,使用23端口。
- http服務器,使用80端口。
- https服務器,使用443端口。
查看知名端口號
我們可以查看/etc/services
文件,該文件是記錄網絡服務名和它們對應使用的端口號及協議。
說明一下:?文件中的每一行對應一種服務,它由4個字段組成,每個字段之間用TAB或空格分隔,分別表示“服務名稱”、“使用端口”、“協議名稱”以及“別名”。
我們自己寫一個程序使用端口號時, 要避開這些知名端口號
兩個問題
一個端口號是否可以被多個進程綁定?
一個端口號絕對不能被多個進程綁定,因為端口號的作用就是唯一標識一個進程,如果綁定一個已經被綁定的端口號,就會出現綁定失敗的問題。
一個進程是否可以綁定多個端口號?
一個進程是可以綁定多個端口號的,這與“端口號必須唯一標識一個進程”是不沖突的,只不過現在這多個端口唯一標識的是同一個進程罷了。
我們限制的是從端口號到進程的唯一性,而沒有要求從進程到端口號也必須滿足唯一性,因此一個進程是可以綁定多個端口號的。
netstat與iostat
netstat命令
netstat
是一個用來查看網絡狀態的重要工具。
其常見的選項如下:
- n:拒絕顯示別名,能顯示數字的全部轉換成數字。
- l:僅列出處于LISTEN(監聽)狀態的服務。
- p:顯示建立相關鏈接的程序名。
- t(tcp):僅顯示tcp相關的選項。
- u(udp):僅顯示udp相關的選項。
- a(all):顯示所有的選項,默認不顯示LISTEN相關。
查看TCP相關的網絡信息時,一般選擇使用nltp
組合選項。
而查看UDP相關的網絡信息時,一般選擇使用nlup
組合選項。?
如果想查看LISTEN狀態以外的連接信息,可以去掉l
選項,此時就會將處于其他狀態的連接信息顯示出來。
iostat命令?
iostat
主要用于輸出磁盤IO和CPU的統計信息。?
其常見的選項如下:
- c:顯示CPU的使用情況。
- d:顯示磁盤的使用情況。
- N:顯示磁盤列陣(LVM)信息。
- n:顯示NFS使用情況。
- k:以KB為單位顯示。
- m:以M為單位顯示。
- t:報告每秒向終端讀取和寫入的字符數和CPU的信息。
- V:顯示版本信息。
- x:顯示詳細信息。
- p:顯示磁盤分區的情況。
比如我們要查看磁盤IO和CPU的詳細信息。
CPU屬性值說明:
- %user:CPU處在用戶模式下的時間百分比。
- %nice:CPU處在帶NICE值的用戶模式下的時間百分比。
- %system:CPU處在系統模式下的時間百分比。
- %iowait:CPU等待輸入輸出完成時間的百分比。
- %steal:管理程序維護另一個虛擬處理器時,虛擬CPU的無意識等待時間百分比。
- %idle:CPU空閑時間百分比。
?
pidof
pidof
命令可以通過進程名,查看進程id。
例如,我們用pidof
命令查看我們自己編寫的一個死循環進程。
?pidof
命令可以配合kill
命令快速殺死一個進程。
UDP協議
UDP協議格式
UDP的位置
網絡套接字編程時用到的各種接口,是位于應用層和傳輸層之間的一層系統調用接口,這些接口是系統提供的,我們可以通過這些接口搭建上層應用,比如HTTP。我們經常說HTTP是基于TCP的,實際就是因為HTTP在TCP套接字編程上搭建的。
而socket接口往下的傳輸層實際就是由操作系統管理的,因此UDP是屬于內核當中的,是操作系統本身協議棧自帶的,其代碼不是由上層用戶編寫的,UDP的所有功能都是由操作系統完成,因此網絡也是操作系統的一部分。
UDP協議格式
UDP協議格式如下:
- 16位源端口號:表示數據從哪里來。
- 16位目的端口號:表示數據要到哪里去。
- 16位UDP長度:表示整個數據報(UDP首部+UDP數據)的長度。
- 16位UDP檢驗和:如果UDP報文的檢驗和出錯,就會直接將報文丟棄。
我們在應用層看到的端口號大部分都是16位的,其根本原因就是因為傳輸層協議當中的端口號就是16位的。
UDP如何將報頭與有效載荷進行分離?
?UDP的報頭當中只包含四個字段,每個字段的長度都是16位,總共8字節。因此UDP采用的實際上是一種定長報頭,UDP在讀取報文時讀取完前8個字節后剩下的就都是有效載荷了。
UDP如何決定將有效載荷交付給上層的哪一個協議?
UDP上層也有很多應用層協議,因此UDP必須想辦法將有效載荷交給對應的上層協議,也就是交給應用層對應的進程。
應用層的每一個網絡進程都會綁定一個端口號,服務端進程必須顯示綁定一個端口號,客戶端進程則是由系統動態綁定的一個端口號。UDP就是通過報頭當中的目的端口號來找到對應的應用層進程的。
說明一下:?內核中用哈希的方式維護了端口號與進程ID之間的映射關系,因此傳輸層可以通過端口號得到對應的進程ID,進而找到對應的應用層進程。
如何理解報頭?
操作系統是C語言寫的,而UDP協議又是屬于內核協議棧的,因此UDP協議也一定是用C語言編寫的,UDP報頭實際就是一個位段類型。
UDP數據封裝:
- 當應用層將數據交給傳輸層后,在傳輸層就會創建一個UDP報頭類型的變量,然后填充報頭當中的各個字段,此時就得到了一個UDP報頭。
- 此時操作系統再在內核當中開辟一塊空間,將UDP報頭和有效載荷拷貝到一起,此時就形成了UDP報文。
UDP數據分用:
- 當傳輸層從下層獲取到一個報文后,就會讀取該報文的前8個字節,提取出對應的目的端口號。
- 當傳輸層從下層獲取到一個報文后,就會讀取該報文的錢8個字節,提取出對應的目的端口號。
UDP協議的特點
UDP傳輸的過程就類似于寄信,其特點如下:
- 無連接:知道對端的IP和端口號就直接進行數據傳輸,不需要建立連接。
- 不可靠:沒有確認機制,沒有重傳機制;如果因為網絡故障該段無法發到對方,UDP協議層也不會給應用層返回任何錯誤信息。
- 面向數據報:不能夠靈活的控制讀寫數據的次數和數量。
注意:?報文在網絡中進行路由轉發時,并不是每一個報文選擇的路由路徑都是一樣的,因此報文發送的順序和接收的順序可能是不同的。
面向數據報
應用層交給UDP多長的報文,UDP就原樣發送,既不會拆分,也不會合并,這就叫做面向數據報。
比如用UDP傳輸100個字節的數據:
- 如果發送端調用一次sendto,發送100字節,那么接收端也必須調用對應的一次recvfrom,接收100個字節;而不能循環調用10次recvfrom,每次接收10個字節。
UDP的緩沖區
- UDP沒有真正意義上的發送緩沖區。調用sendto會直接交給內核,由內核將數據傳給網絡層協議進行后續的傳輸動作。
- UDP具有接收緩沖區。但是這個接收緩沖區不能保證收到的UDP報的順序和發送UDP報的順序一致;如果緩沖區滿了,再到達的UDP數據就會被丟棄。
- UDP的socket既能讀,也能寫,因此UDP是全雙工的。
為什么UDP要有接收緩沖區?
如果UDP沒有接收緩沖區,那么就要求上層及時將UDP獲取到的報文讀取上去,如果一個報文在UDP沒有被讀取,那么此時UDP從底層獲取上來的報文數據就會被迫丟棄。
一個報文從一臺主機傳輸到另一臺主機,在傳輸過程中會消耗主機資源和網絡資源。如果UDP收到一個報文后僅僅因為上次收到的報文沒有被上層讀取,而被迫丟棄一個可能并沒有錯誤的報文,這就是在浪費主機資源和網絡資源。
因此UDP本身是會維護一個接收緩沖區的,當有新的UDP報文到來時就會把這個報文放到接收緩沖區當中,此時上層在讀數據的時就直接從這個接收緩沖區當中進行讀取就行了,而如果UDP接收緩沖區當中沒有數據那上層在讀取時就會被阻塞。因此UDP的接收緩沖區的作用就是,將接收到的報文暫時的保存起來,供上層讀取。
UDP使用注意事項
需要注意的是,UDP協議報頭當中的UDP最大長度是16位的,因此一個UDP報文的最大長度是64K(包含UDP報頭的大小)。
然而64K在當今的互聯網環境下,是一個非常小的數字。如果需要傳輸的數據超過64K,就需要在應用層進行手動分包,多次發送,并在接收端進行手動拼裝。
基于UDP的應用層協議
- NFS:網絡文件系統。
- TFTP:簡單文件傳輸協議。
- DHCP:動態主機配置協議。
- BOOTP:啟動協議(用于無盤設備啟動)。
- DNS:域名解析協議。
當然,也包括你自己寫UDP程序時自定義的應用層協議。
參考文獻:
http://t.csdn.cn/3GdFm