「前言」文章內(nèi)容大致是傳輸層協(xié)議,UDP協(xié)議講解。
「歸屬專欄」網(wǎng)絡(luò)編程
「主頁鏈接」個人主頁
「筆者」楓葉先生(fy)
一、傳輸層
HTTP協(xié)議普通用戶認(rèn)為是將請求和響應(yīng)直接發(fā)送到了網(wǎng)絡(luò)當(dāng)中。但實際應(yīng)用層需要先將數(shù)據(jù)交給傳輸層,由傳輸層對數(shù)據(jù)做進(jìn)一步處理后再將數(shù)據(jù)繼續(xù)向下進(jìn)行交付,該過程貫穿整個網(wǎng)絡(luò)協(xié)議棧,最終才能將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)當(dāng)中
傳輸層負(fù)責(zé)在網(wǎng)絡(luò)中提供可靠的數(shù)據(jù)傳輸服務(wù)。它主要解決了主機之間的通信問題。
常見的傳輸層協(xié)議有TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報協(xié)議),傳輸層已經(jīng)是操作系統(tǒng)內(nèi)核部分了
下面學(xué)習(xí)的是UDP協(xié)議,TCP在下一篇。
二、UDP協(xié)議
2.1 再談端口號
重談概念
端口號是在傳輸層中使用的一個標(biāo)識符,用于識別不同的應(yīng)用程序或服務(wù)。它是一個16位的整數(shù)(2字節(jié)),范圍從0到65535
- 端口號的組合由IP地址和端口號一起構(gòu)成了一個套接字(Socket),用于唯一標(biāo)識網(wǎng)絡(luò)中的通信終點。
- 在傳輸層的通信中,源主機使用源端口號,目標(biāo)主機使用目標(biāo)端口號,以便正確地將數(shù)據(jù)傳輸?shù)较鄳?yīng)的應(yīng)用程序或服務(wù)。
- 通過使用不同的端口號,傳輸層可以實現(xiàn)多個應(yīng)用程序同時進(jìn)行通信,保證數(shù)據(jù)的正確傳輸和接收。
端口號的作用
- 端口號(Port)標(biāo)識一個主機上進(jìn)行網(wǎng)絡(luò)通信的不同的應(yīng)用程序,即標(biāo)識主機上進(jìn)程的唯一性
- 從網(wǎng)絡(luò)中獲取的數(shù)據(jù)在進(jìn)行向上交付時,在傳輸層就會提取出該數(shù)據(jù)對應(yīng)的目的端口號,進(jìn)而確定該數(shù)據(jù)應(yīng)該交付給當(dāng)前主機上的哪一個服務(wù)進(jìn)程
- 即在傳輸層協(xié)議的報頭當(dāng)中就會包含與端口相關(guān)的字段
這些概念在套接字篇章都談過了,不再贅述
五元組
在TCP/IP協(xié)議中,用“源IP地址”,“源端口號”,“目的IP地址”,“目的端口號”,“協(xié)議號”這樣一個五元組來標(biāo)識一個通信。
比如有多臺客戶端主機同時訪問服務(wù)器,這些客戶端主機上可能有一個客戶端進(jìn)程,也可能有多個客戶端進(jìn)程,它們都在訪問同一臺服務(wù)器。
而這臺服務(wù)器就是通過“源IP地址”,“源端口號”,“目的IP地址”,“目的端口號”,“協(xié)議號”來識別一個通信的。
2.2.1 端口號范圍劃分
端口號的長度是16位,因此端口號的范圍是0 ~ 65535
:
- 已知端口號(
Well-known Ports
)是指被分配給特定服務(wù)或協(xié)議的端口號,范圍從0到1023 - 動態(tài)端口號(
Dynamic Ports
)是指在使用過程中臨時分配給應(yīng)用程序的端口號,范圍從1024到65535。 -
0 ~ 1023
:知名(已知)端口號。比如HTTP,F(xiàn)TP,SSH等這些廣為使用的應(yīng)用層協(xié)議,它們的端口號都是固定的。 -
1024 ~ 65535
:操作系統(tǒng)動態(tài)分配的端口號??蛻舳顺绦虻亩丝谔柧褪怯刹僮飨到y(tǒng)從這個范圍分配的。
2.2.2 認(rèn)識知名端口號
有些服務(wù)器是非常常用的, 為了使用方便, 人們約定一些常用的服務(wù)器, 都是用以下這些固定的端口號:
- ssh服務(wù)器,使用
22
端口。 - ftp服務(wù)器,使用
21
端口。 - telnet服務(wù)器,使用
23
端口。 - http服務(wù)器,使用
80
端口。 - https服務(wù)器,使用
443
端口。
查看知名端口號:
vim /etc/services
我們自己寫一個程序使用端口號時,要避開這些知名端口號
2.2.3 端口號注意問題
一個進(jìn)程是否可以綁定多個端口號?
- 一個進(jìn)程可以綁定多個端口號。這與“端口號必須唯一標(biāo)識一個進(jìn)程”是不沖突的
- 在某些情況下,一個進(jìn)程可能需要同時提供多個服務(wù)或協(xié)議,或者需要同時監(jiān)聽多個端口來處理不同類型的數(shù)據(jù)
一個端口號是否可以被多個進(jìn)程綁定?
- 一個端口號通常只能被一個進(jìn)程綁定(%99的情況下都是)。每個端口號在一個特定的時間點只能由一個進(jìn)程使用,以確保數(shù)據(jù)的正確傳輸和接收
- 如果綁定一個已經(jīng)被綁定的端口號,就會出現(xiàn)綁定失敗的問題
2.2.4 netstat命令和pidof命令
netstat命令
netstat
是一個用于顯示網(wǎng)絡(luò)連接、路由表和網(wǎng)絡(luò)接口信息的命令
netstat
英文全稱:network statistics
網(wǎng)絡(luò)統(tǒng)計
常用選項:
-
-a
:all (顯示所有連接和監(jiān)聽端口) -
-t
:tcp (僅顯示TCP連接) -
-u
:udp (僅顯示UDP連接) -
-n
:numeric (以數(shù)字形式顯示IP地址和端口號) -
-p
:program (顯示與連接關(guān)聯(lián)的進(jìn)程信息) -
-l
:listen(僅列出有在 Listen (監(jiān)聽) 的服務(wù)狀態(tài)) -
-r
:route (顯示路由表信息) -
-s
:statistics (顯示網(wǎng)絡(luò)統(tǒng)計信息)
命令演示
查看TCP相關(guān)的網(wǎng)絡(luò)信息時,一般選擇使用-nltp
組合選項。
netstat -nltp
查看UDP相關(guān)的網(wǎng)絡(luò)信息時,一般選擇使用-lnup
組合選項。
netstat -lunp
pidof命令
pidof
命令是一個用于查找正在運行的進(jìn)程的命令。它可以通過進(jìn)程名來查找與之匹配的進(jìn)程的進(jìn)程ID(PID),比較方便
語法: pidof [進(jìn)程名]
功能:通過進(jìn)程名,查看進(jìn)程id
命令演示
可以組合使用
pidof test | xargs kill -9
注:xargs
是一個用于構(gòu)建和執(zhí)行命令行的實用程序。它從標(biāo)準(zhǔn)輸入中讀取數(shù)據(jù),并將其作為參數(shù)傳遞給指定的命令
2.2 UDP協(xié)議格式
UDP協(xié)議格式如下:
前8個字節(jié)是UDP的報頭,報頭包括:
- 16位源端口號:表示數(shù)據(jù)從哪里來。
- 16位目的端口號:表示數(shù)據(jù)要到哪里去。
- 16位UDP長度:表示整個數(shù)據(jù)報(UDP首部+UDP數(shù)據(jù))的長度,即UDP的報文最大長度是
64KB
。 - 16位UDP檢驗和:如果UDP報文的檢驗和出錯,就會直接將報文丟棄。
數(shù)據(jù)部分(用戶數(shù)據(jù))可有可無,數(shù)據(jù)部分就是有效載荷
UDP如何將報頭與有效載荷進(jìn)行分離?
UDP的報頭已經(jīng)規(guī)定大小,即UDP采用定長報頭,UDP在讀取報文時讀取完前8個字節(jié)后剩下的就都是有效載荷
UDP如何決定將有效載荷交付給上層的哪一個協(xié)議?
- UDP是通過報頭當(dāng)中的目的端口號來找到對應(yīng)的應(yīng)用層進(jìn)程的,即由目的端口號決定。
- 當(dāng)UDP數(shù)據(jù)報到達(dá)時,操作系統(tǒng)會根據(jù)目的端口號找到相應(yīng)的應(yīng)用程序或服務(wù),并將數(shù)據(jù)報交付給它進(jìn)行處理
理解協(xié)議的報頭
Linux內(nèi)核是用C語言寫的,UDP/TCP協(xié)議處于內(nèi)核中,所以所謂的報頭就是一種結(jié)構(gòu)化的數(shù)據(jù)對象
比如UDP,下圖左邊是位段寫法
數(shù)據(jù)封裝:
以UDP為例,應(yīng)用層將數(shù)據(jù)交給傳輸層時,傳輸層會創(chuàng)建一個UDP報頭,并填充報頭中的各個字段,包括源端口號和目的端口號等信息。然后,操作系統(tǒng)會在內(nèi)核中開辟一塊空間,將UDP報頭和有效載荷(即應(yīng)用層數(shù)據(jù))拷貝到一起,形成UDP報文
分用
以UDP為例,當(dāng)傳輸層從下層獲取到一個報文后,就會讀取該報文的前8個字節(jié),提取出對應(yīng)的目的端口號。通過目的端口號找到對應(yīng)的上層應(yīng)用層進(jìn)程,然后將剩下的有效載荷向上交付給該應(yīng)用層進(jìn)程
2.3 UDP的特點
UDP傳輸?shù)倪^程就類似于寄信,其特點如下:
- 無連接:知道對端的IP和端口號就直接進(jìn)行數(shù)據(jù)傳輸,不需要建立連接。
- 不可靠:沒有確認(rèn)機制,沒有重傳機制;如果因為網(wǎng)絡(luò)故障該段無法發(fā)到對方,UDP協(xié)議層也不會給應(yīng)用層返回任何錯誤信息。
- 面向數(shù)據(jù)報:不能夠靈活的控制讀寫數(shù)據(jù)的次數(shù)和數(shù)量。
無連接,在套接字代碼已經(jīng)體現(xiàn)到了(與TCP相比),不解釋;不可靠學(xué)了TCP就懂了
下面解釋一下數(shù)據(jù)報
面向數(shù)據(jù)報
- 應(yīng)用層交付給UDP多長的報文,UDP就原樣發(fā)送,既不會拆分,也不會合并,這就叫做面向數(shù)據(jù)報。
- 可以想像成快遞:你朋友給你發(fā)了1個快遞,你就只能收1個快遞,你不能只收0.5個快遞,也不能收2個快遞,你只能收1個,即發(fā)多少就收多少。對比讀數(shù)據(jù)
- UDP發(fā)送的數(shù)據(jù)不能太大,UDP的報文最大長度是64KB(UDP首部+UDP數(shù)據(jù))
- 如果超過 64KB了,必須進(jìn)行拆分,拆分的每個小數(shù)據(jù)都必需比64KB小,這個是應(yīng)用層寫代碼自己做的工作。如果超了,就發(fā)不了
- 比如用UDP傳輸100個字節(jié)的數(shù)據(jù),發(fā)送端調(diào)用一次發(fā)送函數(shù),發(fā)送100字節(jié),那么接收端也必須調(diào)用對應(yīng)的一次接收函數(shù),接收100個字節(jié);如果發(fā)送端調(diào)用十次發(fā)送函數(shù),則接收端也必須調(diào)用對應(yīng)的十次接收函數(shù),即UDP協(xié)議,發(fā)送函數(shù)的次數(shù) : 接收函數(shù)的次數(shù) = 1 : 1
2.4 UDP的緩沖區(qū)
- UDP沒有真正意義上的發(fā)送緩沖區(qū)。調(diào)用sendto會直接交給內(nèi)核,由內(nèi)核將數(shù)據(jù)傳給網(wǎng)絡(luò)層協(xié)議進(jìn)行后續(xù)的傳輸動作。
- UDP具有接收緩沖區(qū)。但是這個接收緩沖區(qū)不能保證收到的UDP報的順序和發(fā)送UDP報的順序一致;如果緩沖區(qū)滿了,再到達(dá)的UDP數(shù)據(jù)就會被丟棄。
緩沖區(qū)以TCP為例
發(fā)送接收數(shù)據(jù):
- 發(fā)送函數(shù)(write等)在自己的應(yīng)用層有自己的應(yīng)用層發(fā)送緩沖區(qū),調(diào)用發(fā)送函數(shù)實際上是把數(shù)據(jù)拷貝到傳輸層的發(fā)送緩沖區(qū)中
- 數(shù)據(jù)是否發(fā)送到網(wǎng)絡(luò)中,由TCP協(xié)議自主決定,所以TCP協(xié)議稱為傳輸控制協(xié)議,關(guān)鍵字:傳輸控制
- 接收函數(shù)(read等)在自己的應(yīng)用層也有自己的應(yīng)用層接收緩沖區(qū),調(diào)用接收函數(shù)實際上是把傳輸層接受緩沖區(qū)中數(shù)據(jù)拷貝到自己應(yīng)用層接收緩沖區(qū)中
- 所以
read、write、send、recv、sendto
等函數(shù)本質(zhì)上是拷貝函數(shù) - 一方在發(fā)送,另一方也在發(fā)送,雙方根本就不會影響,因為它們有成對的緩沖區(qū),一個負(fù)責(zé)發(fā)送,一個負(fù)責(zé)接收,所以TCP是全雙工的
- 這對緩沖區(qū)有生產(chǎn)消費模型的思想,兼具該模型的優(yōu)點
為什么UDP沒有發(fā)送緩沖區(qū)
- 因為不需要,UDP協(xié)議的設(shè)計目標(biāo)是提供一種簡單的、無連接的通信方式。
- UDP協(xié)議的設(shè)計初衷是為了實現(xiàn)高效的數(shù)據(jù)傳輸,盡量減少協(xié)議本身的開銷。
- UDP協(xié)議并不提供可靠性和流量控制的機制,因此不需要發(fā)送緩沖區(qū)
- 調(diào)用sendto會把數(shù)據(jù)直接交給內(nèi)核,由內(nèi)核將數(shù)據(jù)傳給網(wǎng)絡(luò)層協(xié)議進(jìn)行后續(xù)的傳輸動作。
為什么UDP要有接收緩沖區(qū)?
如果UDP沒有接收緩沖區(qū),那么就要求上層及時將UDP獲取到的報文讀取上去,如果一個報文在UDP沒有被讀取,那么此時UDP從底層獲取上來的報文數(shù)據(jù)就會被迫丟棄。
注意:UDP接收緩沖區(qū)滿了,再來報文直接丟棄
UDP需要有接收緩沖區(qū)是為了應(yīng)對網(wǎng)絡(luò)傳輸中的不可靠性和不確定性。
因為UDP本身是不可靠的,所以接收方可能會面臨以下情況:
- 數(shù)據(jù)到達(dá)的速度快于應(yīng)用程序的處理速度:如果接收方的應(yīng)用程序無法及時處理到達(dá)的數(shù)據(jù)報,那么接收緩沖區(qū)可以暫時存儲這些數(shù)據(jù),避免數(shù)據(jù)丟失。
- 數(shù)據(jù)到達(dá)的順序可能不同于發(fā)送順序:由于UDP的無連接性,數(shù)據(jù)報可能以不同的順序到達(dá)接收方。接收緩沖區(qū)可以暫時存儲這些亂序的數(shù)據(jù)報,并按照應(yīng)用程序的需要進(jìn)行排序和組裝。
- 網(wǎng)絡(luò)擁塞或丟包:在網(wǎng)絡(luò)傳輸中,可能會發(fā)生丟包或擁塞的情況。接收緩沖區(qū)可以緩沖部分?jǐn)?shù)據(jù),以便在網(wǎng)絡(luò)恢復(fù)正常后重新接收丟失的數(shù)據(jù)。
雖然UDP沒有發(fā)送緩沖區(qū),但是UDP的socket既能讀,也能寫,所以也是全雙工
2.5 UDP注意事項
上面已經(jīng)談過了文章來源:http://www.zghlxwxcb.cn/news/detail-580858.html
- 需要注意的是,UDP協(xié)議報頭當(dāng)中的UDP最大長度是16位的,因此一個UDP報文的最大長度是64K(包含UDP報頭的大?。?/li>
- 然而64K在當(dāng)今的互聯(lián)網(wǎng)環(huán)境下,是一個非常小的數(shù)字。如果需要傳輸?shù)臄?shù)據(jù)超過64K,就需要在應(yīng)用層進(jìn)行手動分包,多次發(fā)送,并在接收端進(jìn)行手動拼裝。
2.6 基于UDP的應(yīng)用層協(xié)議
- NFS:網(wǎng)絡(luò)文件系統(tǒng)。
- TFTP:簡單文件傳輸協(xié)議。
- DHCP:動態(tài)主機配置協(xié)議。
- BOOTP:啟動協(xié)議(用于無盤設(shè)備啟動)。
- DNS:域名解析協(xié)議。
--------------------- END ----------------------文章來源地址http://www.zghlxwxcb.cn/news/detail-580858.html
「 作者 」 楓葉先生
「 更新 」 2023.7.18
「 聲明 」 余之才疏學(xué)淺,故所撰文疏漏難免,
或有謬誤或不準(zhǔn)確之處,敬請讀者批評指正。
到了這里,關(guān)于「網(wǎng)絡(luò)編程」傳輸層協(xié)議_ UDP協(xié)議學(xué)習(xí)_及原理深入理解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!