正如標題所寫。這篇文章致力於網絡協議的初級掃盲、方便應對日常甚至面試中的尬聊、也是爲了對剛補完的網絡協議做個歸納。
目錄
- TCP/IP協議族的體系結構
- 四層協議模型
- 每層的作用
- TCP/IP協議整體的工作流程
- 網絡層
- 傳輸層
- 應用層
- 最後:網絡協議到底有沒有用?
TCP/IP協議族的體系結構
-
四層協議模型
雖然與OSI有所不同、但也只是將某些層級合併了而已。
有人說是四層、也有人說是五層(將網絡接口層分爲數據鏈路層和物理層
)。但是畢竟是個認爲定義的東西、沒必要拼個你死我活、理解每一層的作用就好(也有人說ARP以及RARP該歸屬物理鏈路層、一樣沒必要爭論
)。
-
每層的作用
嘗試性的總結以及類比一下、但是不確保100%吻合、因爲現實畢竟和網絡上不同(你見過誰家快遞員專職住你公司裏簽單子?)。
- 四層結構(橙色)全部處於主機內部、並且
源主機
和目標主機
甚至路由器
都含有它們。 - 應用層並不代指APP、而是供APP調用(
比如HTTP
)。 - 傳輸層負責這次傳輸的具體規則(
重發、擁塞控制)
。 - 網絡層只負責傳輸、其餘全部不管。
- 物理鏈路層實際上就是網卡(
比如以前手機的網卡不能連wifi
)。
-
TCP/IP協議整體的工作流程
原始數據包會經過一層一層的封裝(爲了讓下一層能夠識別必須添加特定的包頭
)、向下傳遞。而後在目的地一層一層將數據取出。
網絡層
是TCP/IP協議中最重要的一層
-
路由器是如何工作的?--路由協議
-
路由器
負責報文(數據包)的轉發以及路徑的選擇
包括但不限於家用路由器、這裏更多的指運營商處的大型路由器。
路由表
路徑選擇
主要依靠路由表
(也就是通過我可以到達網絡的表格)實現。包括靜態路由表(網絡管理員負責建立、但基本沒人用
)以及動態路由表(通過路由協議建立
)。
工作原理
- 如果目的地址存在於路由表中、那麼直接轉發。
- 如果目的地址不存在於路由表中、那麼則發給默認路由。
- 通過網絡號而不是整個IP地址進行路由判斷
-
路由協議
幫助路由器建立路由表
分爲兩種算法實現:
距離向量路由算法
要求路由器將自己的路由表發送到臨近的節點上
鏈路狀態路由算法
只發送路由表中描述自身鏈路狀態的部分到臨近的節點上
二者比較
鏈路狀態算法
相比距離向量算法
在大型網絡上更有優勢。
由於發送的數據更精簡、所以收斂速度更快、網絡開銷也更小。
路由表到底有多大?
具體要看與自己需要選擇轉發的網絡有多大。
比如、對於家用路由器的路由表自然只要維護自己內部的主機就好、一旦發現數據包不數據自己內部就直接丟給默認端口(當然大型路由器也一樣)。
具體可以參閱《網絡協議補完計劃--路由協議》
————————
-
IP地址是個啥?IP協議
一種無連接的傳輸協議。只負責數據包的傳輸、不對任何問題負責。
其實和UDP很像、但是IP數據包的包頭中是不含端口號的、只針對主機(IP地址)之間進行傳輸。
A、B、C、D、E共五類網絡地址
常用的網絡地址爲ABC三類:
A類:0開頭、後24位作爲主機號、其餘作爲網絡號。
B類:10開頭、後16位作爲主機號、其餘作爲網絡號。
C類:110開頭、後8位作爲主機號、其餘作爲網絡號(最常用)
D類:用於UDP多播。
子網掩碼
對地址結構的擴展、用於確定網絡號與主機號的結構
比如有兩個C類地址、他們本屬不同的網絡。但如果合理使用子網技術、就可以把他們的網絡號合併從而形成一個子網。
分片與重組
實際使用中經常會遇到一個IP包傳輸不完(
比如途中某個物理網絡最大傳輸長度限制
)、需要拆分的情況。
對於大於MTU(最大傳輸長度
)的數據包、會被拆分然後傳輸、最後在目的地重組恢復。
分片動作通常由路由器完成、重組由目標主機完成(降低了中間路由器壓力)。
需要注意的是一旦任何分片丟失、目的主機都會要求重傳所有分片
NAT網絡地址轉換
一種通過將內部不同
私網IP及端口
與公網端口綁定
、以達到內部所有計算機
通過一個公網IP
進行外界溝通的作用。
我們現在基本都是使用了這個技術、如果你有兩臺主機就會發現他們的公網IP其實是相同的。
這個技術在很大程度上也緩解了IP地址不足的問題(雖然不能根治)。
具體可以參閱《網絡協議補完計劃--IP協議》
————————
-
未來的新型IP地址--IPv6
- 擴展地址
有IPv4的32(46億個
)位擴展爲128位(340萬億個
) - 簡化的包頭
- 流標記
相同流向的數據包不需要每次進行尋路
具體可以參閱《網絡協議補完計劃--IPv6》
————————
-
MAC地址有什麼作用?--ARP協議
用IP地址映射所對應的MAC地址
在物理層上、並不是通過IP地址來確定通訊目標(有可能是因爲網絡興起初期協議很多、IP協議並不佔主導
)、而是通過網卡的MAC地址。
IP地址指向最終的主機地址、而MAC地址指向下一跳的目標位置。
工作流程
①當電腦沒有網關(採用代理ARP)時:"跨網段訪問誰,就問誰的MAC"
②當電腦有網關(採用正常ARP)時:"跨網段訪問誰,都問網關的MAC"
③無論哪種ARP,跨網段通信時,發送方請求得到的目標MAC地址都是網關MAC。
與之對應的還有RARP協議(用於網絡中某些需要遠程啓動的無盤工作站獲取IP地址
)
具體可以參閱《網絡協議補完計劃--ARP協議和RARP協議》
————————
-
我們總說ping一下。本質是個啥?--ICMP協議
發現錯誤的路由器、向數據包的(通過IP數據包的信息獲取)源主機地址發送一個ICMP數據包、並且通過ICMP數據包報告出錯的原因。
ICMP協議是IP協議的補充、
ICMP與IP協議位於同一個層次
(IP層),但ICMP報文是封裝在IP數據包的數據部分
進行傳輸的。-
總的來看可以分爲如圖所示的三大 類:差錯報告、控制報文和請求應答報文:
大部分都是給源路由器看的(比如網絡不可達
/源抑制
等等)
我們日常用到的ping命令
:作用就是我們發送請求報文
、目標服務器返回一個應答報文
以此判斷目標主機是否存在
。
具體可以參閱《網絡協議補完計劃--ICMP協議》
————————
如何動態分配IP地址?--廣播與多播
動態主機配置協議(Dynamic Host Configuration Protocol,DHCP),在認定本地子網上有一個DHCP服務器主機或中繼主機的前提下,DHCP客戶主機向廣播地址(通常是255.255.255.255,因爲客戶主機還不知道自己的IP地址、子網掩碼及本子網的受限廣播地址)發送自己的請求。
單播
點對點的通訊方式廣播(IPv4)
向所有的主機同時通訊多播(組播)
向某些主機同時通訊泛播(IPv6)
向任意一些主機中的某一個發起通訊。可以參照負載均衡來理解、我想知道當前時間、10個服務器有資格響應、但最終只有一個離我最近的服務器完成響應
。
注意這裏雖然在網絡層所提到的廣播多播、也就是通過特定的IP地址實現。例如:
主機位全部爲1(xxx.xxx.xxx.255
)則爲該網絡的廣播地址。
但並不妨礙我們在UDP中使用:
比如我們可以監聽一個端口、然後向本地廣播地址發送UDP數據包
進行本地羣組聊天
或者通過單播地址
來點對點聊天
。
TCP不支持廣播和多播:具體等說到TCP時再說。
具體可以參閱《網絡協議補完計劃--廣播與多播》
傳輸層
在運行在不同主機上的進程提供邏輯通訊的功能、使彼此感覺直接相連
-
套接字(socket)
總是成對出現、是應用層到傳輸層的門戶。
套接字本質上就是操作系統爲傳輸層公開的API、幫助我們組裝傳輸層數據包並交給IP層發送。
套接字(socket
)並不單指TCP(長連接
)、TCP/IP協議族中包括三種套接字:
- 流式套接字--TCP協議專屬
- 數據報套接字--UDP協議專屬
- 原始套接字--可以直接訪問IP層
我們可以舉個C語言socket編程的例子:
//創建一個TCP的scoket
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//創建一個UDP的scoket
SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
——————
-
UDP協議--(用戶數據報協議(User Datagram Protocol))
不可靠的無連接的數據包傳輸服務
只負責發送、不保證安全性(確認到達)以及順序。這點其實和IP協議的本質一樣。
所以、UDP可以在不建立連接的情況下隨意向主機的某個端口發送數據(但源主機並不知道是否發送成功、甚至目標主機都不知道是誰發來的數據
)。
-
TCP協議--(傳輸控制協議Transmission Control Protocol))
面向鏈接的可靠的字節流傳輸服務
即TCP協議數據包會保證重發、有序還有擁塞控制。確保從發送方發出的數據、按照順序完整的交付給接收方。
所以、TCP鏈接需要經歷三次握手(雙方確認相互可以收發數據
)、四次揮手(雙方先後申請斷開單向鏈接並被確認
)
此外TCP是全雙工的、數據的發送、接收可以同時雙向進行。
————————
-
TCP協議與UDP協議的比較
借用《《知乎》》上的一個很有趣的例子:
亞當和夏娃分別生活在兩個山頭,山頭之間是萬丈深淵,亞當採集野果需要分享給夏娃,如果他們之間有一條索道(物理連接),野果可以順着索道滑到夏娃那一邊,那就沒有網絡協議什麼事了。
事實上山頭之間沒有索道。但是亞當何等聰明,於是他想出了一個方法,假設亞當需要給夏娃10個野果,否則她會餓死。
============================
《《《《《《對於TCP》》》》》》
============================
連接建立
亞當對着夏娃大喊:愛妃,你聽得到嗎?
夏娃迴應:孩他爹,我聽得到!
亞當接着喊:那好,我扔果子給你吃,你接到果子就喊一聲,一共十個。
運送貨物
於是亞當開始扔第一個,夏娃喊收到了一個。
亞當扔第二個,夏娃喊收到兩個。
超時重傳 ( timeout retransmit)
亞當扔第三個,可是夏娃遲遲沒有迴音,亞當意識到可能果子落到懸崖了,於是重新扔,夏娃喊收到第三個。
Advertised window size = 0
於是亞當連續扔了第四、五、六個,夏娃急了:孩他爹,慢點扔,臣妾忙不過來了…
Advertised window size > 0
於是亞當坐下休息,愛妃又開始叫了:繼續扔吧。
亞當開始扔第七個,夏娃喊收到七個。
…
關閉連接
終於亞當扔完了,亞當喊:愛妃,果子扔完了,寡人去忙別的了。
夏娃回覆:好的,我也休息一下,再見。
亞當:再見
以上的過程類似TCP連接的過程,TCP是一個虛擬連接
============================
《《《《《《對於UDP》》》》》》
============================
亞當和夏娃吵架了,任憑亞當如何大聲喊,夏娃躲在樹林後生悶氣,一聲不響,亞當害怕夏娃餓死,於是
開始自說自話朝着夏娃的山頭扔玉米棒子:
一個、兩個、三個…
一共扔了十個,但最終扔到對方山頭到底有幾個,亞當沒有底,也許有的玉米棒子落到懸崖了,但是這個效率高啊,可以連續扔,以前扔10個果子需要一分鐘,現在只需要20秒。
亞當扔果子、扔玉米都有可能扔到懸崖下,但是扔果子爲何可以確保對方收到十個?那是因爲夏娃收到一個果子,然後喊收到了,如果沒有收到,亞當就重新扔,直到夏娃說收到了。而扔玉米棒子對方沒有確認,所以對於丟棄的情況無法知道,也無法重新扔。
面向連接的傳輸服務
-
TCP以連接作爲協議數據的最終目標
TCP協議的端口是可以複用
對於TCP協議,要成功建立一個新的鏈接,需要保證新鏈接四個要素組合體的唯一性:客戶端的IP、客戶端的port、服務器端的IP、服務器端的port。也就是說,服務器端的同一個IP和port,可以和同一個客戶端的多個不同端口成功建立多個TCP鏈接(與多個不同的客戶端當然也可以),只要保證【Server IP + Server Port + Client IP + Client Port】這個組合唯一不重複即可。
-
UDP以端口作爲協議數據的最終目標
UDP協議的端口不可複用
對於UDP協議、是以監聽端口作爲操作的。而且在協議中、源端口和源IP地址都是可選項。哪怕不填(只制定了目的端口和目的地址)也可以成功發送。
-
TCP協議需要先建立連接、然後才能發送/接收數據
並且需要對很多細節進行協商(最大數據長度、窗口大小、初始序列號等) - UDP協議直接發送/接收數據
可靠的傳輸服務
-
TCP協議提供的是可靠的傳輸服務
以序列號保證有序、以重發機制保證成功發送。 -
UDP協議提供的是不可靠的傳輸服務
可能會丟失、失序、重複等。
面向字節流的傳輸服務
-
TCP協議是以字節爲單位流式傳輸數據
TCP的傳輸是無邊界的 -
UDP協議是以數據塊傳輸數據
UDP的傳輸是有邊界的
——————————
-
TCP應用於UDP應用
1. TCP
以可靠傳輸爲基準:FTP、Telnet、http、自建通道。
2. UDP
對時效性爲基準:實時應用、多播式應用。
使用UDP時應該注意一下幾點:
1. 應用程序必須自己來保證可靠性
應用程序必須有自己的重發機制、數據失序處理、流量控制等。
2. 應用程序必須自己來處理大塊數據
發送方對大塊數據進行分割、接收方還要進行重組
QQ就是採用《可靠的UDP》+TCP來實現。其中UDP主要負責通訊、TCP負責最低限度狀態的維持。
影響TCP和UDP選擇的最大原因
很多遊戲選擇UDP而非TCP、並不是因爲來回的確認包會浪費資源或者拖慢網速(因爲可靠的UDP也需要確認包
)、更不是三次握手。
更重要的原因是TCP的阻塞窗口機制會《在發生阻塞時自動減少數據段的發送》、一旦網絡發生波動、TCP的這個自宮機制會讓應用程序的延遲更高。而在網絡恢復後、TCP的慢啓動機制也會延緩恢復的時間。
關於TCP和UDP具體可以參閱《網絡協議補完計劃--TCP協議》、《網絡協議補完計劃--UDP協議》
應用層
-
HTTP
HTTP連接最顯著的特點是客戶端發送的每次請求都需要服務器回送響應、在
請求結束後(HTTP1.0)恰當的時候(keep-alive)、會主動釋放連接。從建立連接到關閉連接的過程稱爲“一次連接”。
實際上HTTP就是對於TCP的二次封裝、使得我們只需要傳入很少的參數便能使用TCP鏈接以《請求--應答》的方式進行通訊。默認端口爲80.
HTTP1.0:
- 無連接
每次通訊結束會自動釋放鏈接 - 無狀態
服務器無法記錄用戶以前的動作
HTTP1.1:
- 新頭部字段
主機名、身份認證、狀態管理和Cache緩存等 - Connection-Keep-Alive
保持長連接(默認開啓--但是服務器通常會偷偷的釋放掉連接以節省資源
) - 支持在一次連接中同時發出多個請求
但服務器端必須按照接收到客戶端請求的先後順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容。這也叫做《隊首阻塞》。 - 斷點續傳
HTTP2.0:
多路複用
基於二進制分幀層,HTTP 2.0可以在共享TCP連接的基礎上,同時發送請求和響應。HTTP消息被分解爲獨立的幀,而不破壞消息本身的語義,交錯發送出去,最後在另一端根據流ID和首部將它們重新組合起來
。頭部壓縮
更小的頭部體積、傳輸更快
HTTP狀態碼
1xx(臨時響應
)、2xx(請求成功
)、3xx(重定向
)、4xx(客戶機錯誤
)、5xx(服務器錯誤
)。
Cookie
服務器通過響應頭髮送一個用於識別身份的cookie字符串
讓《客戶端保存》、客戶端在之後的請求中將該cookie放在請求頭中發送
。
需要注意的是cookie是不能跨域的、而且https和http共用同一個。
Session
與cookie客戶端保存不同、session是由《服務器生成並保存》每個連接者的身份信息(session)。而這個身份信息與客戶端的cookie綁定、所以也有人說session是基於cookie實現
的。
具體可以參閱《網絡協議補完計劃--HTTP協議》
——————————
HTTPS
負責《幫助服務器和客戶端在安全的環境下協商出一個祕鑰》以《進行加密傳輸》。
主要用到了三種技術:
- 使用
數字證書以及數字簽名
技術實現服務器公鑰認證 - 使用公鑰實現
在非對稱加密
狀態下協商通信祕鑰 - 使用通信祕鑰實現
對稱加密
狀態下的安全通信
具體可以參閱《網絡協議補完計劃--HTTPS》
最後:網絡協議到底有沒有用?
這個問題沒有定論。因爲對於絕大部分人而言、我們只需要瞭解HTTP、甚至連了解都不用只需要會調用API就夠了。
所以具體有沒有用、要看工作中有沒有遇到什麼問題。
當項目足夠大、或許就用得上了。
以美團移動網絡的架構作爲例舉
這個架構圖基本上已經涵蓋了目前所有的通訊方式、並加以合理利用
TCP子通道:
專用的TCP長連接通道。所有客戶端的HTTP請求默認都會被加工成二進制數據包放在專用的TCP通道發送給代理服務器。
UDP子通道:
作爲TCP的降級方案使用、如果TCP不同則嘗試使用UDP通道通訊。
HTTP子通道:
當TCP與UDP均不可用、則直接使用HTTP對業務服務器進行公網請求。
HTTP通道:
上傳和下載大數據包的請求如果放在長連上進行都有可能導致長連通道的擁堵,因此我們將CDN訪問、文件上傳和頻繁的日誌上報等放在公網利用HTTP短連進行請求,同時也減輕代理長連服務器的負擔。
WNS通道:
出於災備用TCP通道