太棒了!TCP/IP协议 (图解+秒懂+史上最全)
TCP/IP協議的分層模型
在展開介紹TCP/IP協議之前,首先介紹一下七層ISO模型。國際標準化組織ISO為了使網絡應用更為普及,推出了OSI參考模型,即開放式系統互聯(Open
System Interconnect)模型,
一般都叫OSI參考模型。OSI參考模型是ISO組織在1985年發布的網絡互連模型,其含義就是為所有公司使用一個統一的規范來控制網絡,這樣所有公司遵循相同的通信規范,網絡就能互聯互通了。
OSI模型的七層框架
OSI模型定義了網絡互連的七層框架(物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層),每一層實現各自的功能和協議,并完成與相鄰層的接口通信。OSI模型各層的通信協議,大致舉例如下表所示:
表:OSI模型各層的通信協議舉例
| 應用層 | HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP、等等 |
| 表示層 | XDR、ASN.1、SMB、AFP、NCP、等等 |
| 會話層 | ASAP、SSH、RPC、NetBIOS、ASP、Winsock、BSD Sockets、等等 |
| 傳輸層 | TCP、UDP、TLS、RTP、SCTP、SPX、ATP、IL、等等 |
| 網絡層 | IP、ICMP、IGMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25、等等 |
| 數據鏈路層 | 以太網、令牌環、HDLC、幀中繼、ISDN、ATM、IEEE 802.11、FDDI、PPP、等等 |
| 物理層 | 例如銅纜、網線、光纜、無線電等等 |
TCP/IP協議是Internet互聯網最基本的協議,其在一定程度上參考了七層ISO模型。OSI模型共有七層,從下到上分別是物理層、數據鏈路層、網絡層、運輸層、會話層、表示層和應用層。但是這顯然是有些復雜的,所以在TCP/IP協議中,七層被簡化為了四個層次。TCP/IP模型中的各種協議,依其功能不同,被分別歸屬到這四層之中,常被視為是簡化過后的七層OSI模型。
TCP/IP協議與七層ISO模型的對應關系
TCP/IP協議與七層ISO模型的對應關系,大致如下圖所示:
圖:TCP/IP協議與七層ISO模型的對應關系
TCP/IP協議的應用層的主要協議有HTTP、Telnet、FTP、SMTP等,是用來讀取來自傳輸層的數據或者將數據傳輸寫入傳輸層;傳輸層的主要協議有UDP、TCP,實現端對端的數據傳輸;網絡層的主要協議有ICMP、IP、IGMP,主要負責網絡中數據包的傳送等;鏈路層有時也稱作數據鏈路層或網絡接口層,主要協議有ARP、RARP,
通常包括操作系統中的設備驅動程序和計算機中對應的網絡接口卡,它們一起處理與傳輸媒介(如電纜或其他物理設備)的物理接口細節。
(一)TCP/IP協議的應用層
應用層包括所有和應用程序協同工作,并利用基礎網絡交換應用程序的業務數據的協議。一些特定的程序被認為運行在這個層上,該層協議所提供的服務能直接支持用戶應用。應用層協議包括HTTP(萬維網服務)、FTP(文件傳輸)、SMTP(電子郵件)、SSH(安全遠程登陸)、DNS(域名解析)以及許多其他協議。
(二)TCP/IP協議的傳輸層
傳輸層的協議,解決了諸如端到端可靠性問題,能確保數據可靠的到達目的地,甚至能保證數據按照正確的順序到達目的地。傳輸層的主要功能大致如下:
(1)為端到端連接提供傳輸服務;
(2)這種傳輸服務分為可靠和不可靠的,其中TCP是典型的可靠傳輸,而UDP則是不可靠傳輸;
(3)為端到端連接提供流量控制、差錯控制、QoS(Quality of
Service)服務質量等管理服務。
傳輸層主要有兩個性質不同的協議:TCP傳輸控制協議和UDP用戶數據報協議。
TCP協議是一個面向連接的、可靠的傳輸協議,它提供一種可靠的字節流,能保證數據完整、無損并且按順序到達。TCP盡量連續不斷地測試網絡的負載并且控制發送數據的速度以避免網絡過載。另外,TCP試圖將數據按照規定的順序發送。
UDP協議是一個無連接的數據報協議,是一個“盡力傳遞”和“不可靠”協議,不會對數據包是否已經到達目的地進行檢查,并且不保證數據包按順序到達。
總體來說,TCP協議傳輸效率低,但可靠性強;UDP協議傳輸效率高,但可靠性略低,適用于傳輸可靠性要求不高、體量小的數據(比如QQ聊天數據)。
(三)TCP/IP協議的網絡層
TCP/IP協議網絡層的作用是在復雜的網絡環境中為要發送的數據報找到一個合適的路徑進行傳輸。簡單來說,網絡層負責將數據傳輸到目標地址,目標地址可以是多個網絡通過路由器連接而成的某一個地址。另外,網絡層負責尋找合適的路徑到達對方計算機,并把數據幀傳送給對方,網絡層還可以實現擁塞控制、網際互連等功能。網絡層協議的代表包括:ICMP、IP、IGMP等。
(四)TCP/IP協議的鏈路層
鏈路層有時也稱作數據鏈路層或網絡接口層,用來處理連接網絡的硬件部分。該層既包括操作系統硬件的設備驅動、NIC(網卡)、光纖等物理可見部分,還包括連接器等一切傳輸媒介。在這一層,數據的傳輸單位為比特。其主要協議有ARP、RARP等。
圖解 物理層:使用MAC解決設備的身份證問題
通信的原始時代
很久很久之前,你不與任何其他電腦相連接,孤苦伶仃。
直到有一天,你希望與另一臺電腦 B 建立通信,于是你們各開了一個網口,用一根網線連接了起來。
用一根網線連接起來怎么就能"通信"了呢?我可以給你講 IO、講中斷、講緩沖區,但這不是研究網絡時該關心的問題。
如果你糾結,要么去研究一下操作系統是如何處理網絡 IO 的,要么去研究一下包是如何被網卡轉換成電信號發送出去的,要么就僅僅把它當做電腦里有個小人在開槍吧~
反正,你們就是連起來了,并且可以通信。
有一天,一個新伙伴 C 加入了,但聰明的你們很快發現,可以每個人開兩個網口,用一共三根網線,彼此相連。
隨著越來越多的人加入,你發現身上開的網口實在太多了,而且網線密密麻麻,混亂不堪。(而實際上一臺電腦根本開不了這么多網口,所以這種連線只在理論上可行,所以連不上的我就用紅色虛線表示了,就是這么嚴謹哈哈~)
集線器的誕生
于是你們發明了一個中間設備,你們將網線都插到這個設備上,由這個設備做轉發,就可以彼此之間通信了,本質上和原來一樣,只不過網口的數量和網線的數量減少了,不再那么混亂。
你給它取名叫集線器,它僅僅是無腦將電信號轉發到所有出口(廣播),不做任何處理,你覺得它是沒有智商的,因此把人家定性在了物理層。
由于轉發到了所有出口,那 BCDE 四臺機器怎么知道數據包是不是發給自己的呢?
首先,你要給所有的連接到交換機的設備,都起個名字。原來你們叫 ABCD,但現在需要一個更專業的,全局唯一的名字作為標識,你把這個更高端的名字稱為?MAC 地址。
你的 MAC 地址是 aa-aa-aa-aa-aa-aa,你的伙伴 b 的 MAC 地址是 bb-bb-bb-bb-bb-bb,以此類推,不重復就好。
這樣,A 在發送數據包給 B 時,只要在頭部拼接一個這樣結構的數據,就可以了。
B 在收到數據包后,根據頭部的目標 MAC 地址信息,判斷這個數據包的確是發給自己的,于是便收下。
其他的 CDE 收到數據包后,根據頭部的目標 MAC 地址信息,判斷這個數據包并不是發給自己的,于是便丟棄。
雖然集線器使整個布局干凈不少,但原來我只要發給電腦 B 的消息,現在卻要發給連接到集線器中的所有電腦,這樣既不安全,又不節省網絡資源。
圖解 數據鏈路:使用交換機解決MAC 地址映射問題
集線器的問題
如果把這個集線器弄得更智能一些,只發給目標 MAC 地址指向的那臺電腦,就好了。
交換機的誕生
雖然只比集線器多了這一點點區別,但看起來似乎有智能了,你把這東西叫做交換機。也正因為這一點點智能,你把它放在了另一個層級,數據鏈路層。
如上圖所示,你是這樣設計的。
交換機內部維護一張?MAC 地址表,記錄著每一個 MAC 地址的設備,連接在其哪一個端口上。
| MAC 地址 | 端口 |
| bb-bb-bb-bb-bb-bb | 1 |
| cc-cc-cc-cc-cc-cc | 3 |
| aa-aa-aa-aa-aa-aa | 4 |
| dd-dd-dd-dd-dd-dd | 5 |
假如你仍然要發給 B 一個數據包,構造了如下的數據結構從網口出去。
到達交換機時,交換機內部通過自己維護的 MAC 地址表,發現目標機器 B 的 MAC 地址 bb-bb-bb-bb-bb-bb 映射到了端口 1 上,于是把數據從 1 號端口發給了 B,完事~
你給這個通過這樣傳輸方式而組成的小范圍的網絡,叫做以太網。
當然最開始的時候,MAC 地址表是空的,是怎么逐步建立起來的呢?
假如在 MAC 地址表為空是,你給 B 發送了如下數據
由于這個包從端口 4 進入的交換機,所以此時交換機就可以在 MAC地址表記錄第一條數據:
MAC:aa-aa-aa-aa-aa-aa-aa
端口:4
交換機看目標 MAC 地址(bb-bb-bb-bb-bb-bb)在地址表中并沒有映射關系,于是將此包發給了所有端口,也即發給了所有機器。
之后,只有機器 B 收到了確實是發給自己的包,于是做出了響應,響應數據從端口 1 進入交換機,于是交換機此時在地址表中更新了第二條數據:
MAC:bb-bb-bb-bb-bb-bb
端口:1
過程如下
經過該網絡中的機器不斷地通信,交換機最終將 MAC 地址表建立完畢~
隨著機器數量越多,交換機的端口也不夠了,但聰明的你發現,只要將多個交換機連接起來,這個問題就輕而易舉搞定~
你完全不需要設計額外的東西,只需要按照之前的設計和規矩來,按照上述的接線方式即可完成所有電腦的互聯,所以交換機設計的這種規則,真的很巧妙。你想想看為什么(比如 A 要發數據給 F)。
但是你要注意,上面那根紅色的線,最終在 MAC 地址表中可不是一條記錄呀,而是要把 EFGH 這四臺機器與該端口(端口6)的映射全部記錄在表中。
MAC 地址和端口的映射記錄
最終,兩個交換機將分別記錄 A ~ H 所有機器的映射記錄。
左邊的交換機
| MAC 地址 | 端口 |
| bb-bb-bb-bb-bb-bb | 1 |
| cc-cc-cc-cc-cc-cc | 3 |
| aa-aa-aa-aa-aa-aa | 4 |
| dd-dd-dd-dd-dd-dd | 5 |
| ee-ee-ee-ee-ee-ee | 6 |
| ff-ff-ff-ff-ff-ff | 6 |
| gg-gg-gg-gg-gg-gg | 6 |
| hh-hh-hh-hh-hh-hh | 6 |
右邊的交換機
| MAC 地址 | 端口 |
| bb-bb-bb-bb-bb-bb | 1 |
| cc-cc-cc-cc-cc-cc | 1 |
| aa-aa-aa-aa-aa-aa | 1 |
| dd-dd-dd-dd-dd-dd | 1 |
| ee-ee-ee-ee-ee-ee | 2 |
| ff-ff-ff-ff-ff-ff | 3 |
| gg-gg-gg-gg-gg-gg | 4 |
| hh-hh-hh-hh-hh-hh | 6 |
這在只有 8 臺電腦的時候還好,甚至在只有幾百臺電腦的時候,都還好,所以這種交換機的設計方式,已經足足支撐一陣子了。
但很遺憾,人是貪婪的動物,很快,電腦的數量就發展到幾千、幾萬、幾十萬。
圖解 傳輸層:IP地址和路由器
二層交換機的問題
交換機已經無法記錄如此龐大的映射關系了。
此時你動了歪腦筋,你發現了問題的根本在于,連出去的那根紅色的網線,后面不知道有多少個設備不斷地連接進來,從而使得地址表越來越大。
那我可不可以讓那根紅色的網線,接入一個新的設備,這個設備就跟電腦一樣有自己獨立的 MAC 地址,而且同時還能幫我把數據包做一次轉發呢?
這個設備就是路由器,它的功能就是,作為一臺獨立的擁有 MAC 地址的設備,并且可以幫我把數據包做一次轉發,你把它定在了網絡層。
注意,路由器的每一個端口,都有獨立的 MAC 地址
好了,現在交換機的 MAC 地址表中,只需要多出一條 MAC 地址 ABAB 與其端口的映射關系,就可以成功把數據包轉交給路由器了,這條搞定。
那如何做到,把發送給 C 和 D,甚至是把發送給 DEFGH.... 的數據包,統統先發送給路由器呢?
不難想到這樣一個點子,假如電腦 C 和 D 的 MAC 地址擁有共同的前綴,比如分別是
C 的 MAC 地址:FFFF-FFFF-CCCC?D 的 MAC 地址:FFFF-FFFF-DDDD
那我們就可以說,將目標 MAC 地址為?FFFF-FFFF-?開頭的,統統先發送給路由器。
這樣是否可行呢?答案是否定的。
IP地址的誕生
我們先從現實中 MAC 地址的結構入手,MAC地址也叫物理地址、硬件地址,長度為 48 位,一般這樣來表示
00-16-EA-AE-3C-40
它是由網絡設備制造商生產時燒錄在網卡的EPROM(一種閃存芯片,通??梢酝ㄟ^程序擦寫)。
其中前 24 位(00-16-EA)代表網絡硬件制造商的編號,后 24 位(AE-3C-40)是該廠家自己分配的,一般表示系列號。
只要不更改自己的 MAC 地址,MAC 地址在世界是唯一的。形象地說,MAC地址就如同身份證上的身份證號碼,具有唯一性。
那如果你希望向上面那樣表示將目標 MAC 地址為?FFFF-FFFF-?開頭的,統一從路由器出去發給某一群設備(后面會提到這其實是子網的概念),那你就需要要求某一子網下統統買一個廠商制造的設備,要么你就需要要求廠商在生產網絡設備燒錄 MAC 地址時,提前按照你規劃好的子網結構來定 MAC 地址,并且日后這個網絡的結構都不能輕易改變。
這顯然是不現實的。
于是你發明了一個新的地址,給每一臺機器一個 32 位的編號,如:
11000000101010000000000000000001
你覺得有些不清晰,于是把它分成四個部分,中間用點相連。
11000000.10101000.00000000.00000001
你還覺得不清晰,于是把它轉換成 10 進制。
192.168.0.1
最后你給了這個地址一個響亮的名字,IP 地址。現在每一臺電腦,同時有自己的 MAC 地址,又有自己的 IP 地址,只不過 IP 地址是軟件層面上的,可以隨時修改,MAC 地址一般是無法修改的。
這樣一個可以隨時修改的 IP 地址,就可以根據你規劃的網絡拓撲結構,來調整了。
如上圖所示,假如我想要發送數據包給 ABCD 其中一臺設備,不論哪一臺,我都可以這樣描述,"將 IP 地址為 192.168.0 開頭的全部發送給到路由器,之后再怎么轉發,交給它!",巧妙吧。
路由器的誕生
路由器誕生了,專門負責IP地址的尋找。那報文交給路由器之后,路由器又是怎么把數據包準確轉發給指定設備的呢?
別急我們慢慢來。
我們先給上面的組網方式中的每一臺設備,加上自己的 IP 地址
現在兩個設備之間傳輸,除了加上數據鏈路層的頭部之外,還要再增加一個網絡層的頭部。
假如 A 給 B 發送數據,由于它們直接連著交換機,所以 A 直接發出如下數據包即可,其實網絡層沒有體現出作用。
但假如 A 給 C 發送數據,A 就需要先轉交給路由器,然后再由路由器轉交給 C。由于最底層的傳輸仍然需要依賴以太網,所以數據包是分成兩段的。
A ~ 路由器這段的包如下:
路由器到 C 這段的包如下:
好了,上面說的兩種情況(A->B,A->C),相信細心的讀者應該會有不少疑問,下面我們一個個來展開。
子網的由來
A 給 C 發數據包,怎么知道是否要通過路由器轉發呢?
答案:子網
如果源 IP 與目的 IP 處于一個子網,直接將包通過交換機發出去。
如果源 IP 與目的 IP 不處于一個子網,就交給路由器去處理。
好,那現在只需要解決,什么叫處于一個子網就好了。
- 192.168.0.1 和 192.168.0.2 處于同一個子網
- 192.168.0.1 和 192.168.1.1 處于不同子網
這兩個是我們人為規定的,即我們想表示,對于 192.168.0.1 來說:
192.168.0.xxx 開頭的,就算是在一個子網,否則就是在不同的子網。
那對于計算機來說,怎么表達這個意思呢?于是人們發明了子網掩碼的概念
假如某臺機器的子網掩碼定為 255.255.255.0
這表示,將源 IP 與目的 IP 分別同這個子網掩碼進行與運算****,相等則是在一個子網,不相等就是在不同子網,就這么簡單。
比如
- A電腦:192.168.0.1 & 255.255.255.0 = 192.168.0.0
- B電腦:192.168.0.2 & 255.255.255.0 = 192.168.0.0
- C電腦:192.168.1.1 & 255.255.255.0 = 192.168.1.0
- D電腦:192.168.1.2 & 255.255.255.0 = 192.168.1.0
那么 A 與 B 在同一個子網,C 與 D 在同一個子網,但是 A 與 C 就不在同一個子網,與 D 也不在同一個子網,以此類推。
所以如果 A 給 C 發消息,A 和 C 的 IP 地址分別 & A 機器配置的子網掩碼,發現不相等,則 A 認為 C 和自己不在同一個子網,于是把包發給路由器,就不管了,之后怎么轉發,A 不關心。
A 如何知道,哪個設備是路由器?
答案:在 A 上要設置默認網關
上一步 A 通過是否與 C 在同一個子網內,判斷出自己應該把包發給路由器,那路由器的 IP 是多少呢?
其實說發給路由器不準確,應該說 A 會把包發給默認網關。
對 A 來說,A 只能直接把包發給同處于一個子網下的某個 IP 上,所以發給路由器還是發給某個電腦,對 A 來說也不關心,只要這個設備有個 IP 地址就行。
所以默認網關,就是 A 在自己電腦里配置的一個 IP 地址,以便在發給不同子網的機器時,發給這個 IP 地址。
僅此而已!
路由表的由來(和Mac表的由來好像,都是逼出來的)
路由器如何知道C在哪里?
答案:路由表
現在 A 要給 C 發數據包,已經可以成功發到路由器這里了,最后一個問題就是,路由器怎么知道,收到的這個數據包,該從自己的哪個端口出去,才能直接(或間接)地最終到達目的地 C 呢。
路由器收到的數據包有目的 IP 也就是 C 的 IP 地址,需要轉化成從自己的哪個端口出去,很容易想到,應該有個表,就像 MAC 地址表一樣。
這個表就叫路由表。
至于這個路由表是怎么出來的,有很多路由算法,本文不展開,因為我也不會哈哈~
不同于 MAC 地址表的是,路由表并不是一對一這種明確關系,我們下面看一個路由表的結構。
| 目的地址 | 子網掩碼 | 下一跳 | 端口 |
| 192.168.0.0 | 255.255.255.0 | 0 | |
| 192.168.0.254 | 255.255.255.255 | 0 | |
| 192.168.1.0 | 255.255.255.0 | 1 | |
| 192.168.1.254 | 255.255.255.255 | 1 |
我們學習一種新的表示方法,由于子網掩碼其實就表示前多少位表示子網的網段,所以如 192.168.0.0(255.255.255.0) 也可以簡寫為 192.168.0.0/24
| 目的地址 | 下一跳 | 端口 |
| 192.168.0.0/24 | 0 | |
| 192.168.0.254/32 | 0 | |
| 192.168.1.0/24 | 1 | |
| 192.168.1.254/32 | 1 |
這就很好理解了,路由表就表示,192.168.0.xxx 這個子網下的,都轉發到 0 號端口,192.168.1.xxx 這個子網下的,都轉發到 1 號端口。下一跳列還沒有值,我們先不管
配合著結構圖來看(這里把子網掩碼和默認網關都補齊了)
剛才說的都是 IP 層,但發送數據包的數據鏈路層需要知道 MAC 地址,可是我只知道 IP 地址該怎么辦呢?
答案:arp
假如你(A)此時不知道你同伴 B 的 MAC 地址(現實中就是不知道的,剛剛我們只是假設已知),你只知道它的 IP 地址,你該怎么把數據包準確傳給 B 呢?
答案很簡單,在網絡層,我需要把 IP 地址對應的 MAC 地址找到,也就是通過某種方式,找到?192.168.0.2?對應的 MAC 地址?BBBB。
這種方式就是?arp 協議,同時電腦 A 和 B 里面也會有一張?arp 緩存表,表中記錄著?IP 與 MAC 地址的對應關系。
| IP 地址 | MAC 地址 |
| 192.168.0.2 | BBBB |
一開始的時候這個表是空的,電腦 A 為了知道電腦 B(192.168.0.2)的 MAC 地址,將會廣播一條 arp 請求,B 收到請求后,帶上自己的 MAC 地址給 A 一個響應。此時 A 便更新了自己的 arp 表。
這樣通過大家不斷廣播 arp 請求,最終所有電腦里面都將 arp 緩存表更新完整。
圖解:整個傳輸過程
從各個節點的視角來看
電腦視角:
- 首先我要知道我的 IP 以及對方的 IP
- 通過子網掩碼判斷我們是否在同一個子網
- 在同一個子網就通過 arp 獲取對方 mac 地址直接扔出去
- 不在同一個子網就通過 arp 獲取默認網關的 mac 地址直接扔出去
交換機視角:
- 我收到的數據包必須有目標 MAC 地址
- 通過 MAC 地址表查映射關系
- 查到了就按照映射關系從我的指定端口發出去
- 查不到就所有端口都發出去
路由器視角:
- 我收到的數據包必須有目標 IP 地址
- 通過路由表查映射關系
- 查到了就按照映射關系從我的指定端口發出去(不在任何一個子網范圍,走其路由器的默認網關也是查到了)
- 查不到則返回一個路由不可達的數據包
如果你嗅覺足夠敏銳,你應該可以感受到下面這句話:
網絡層(IP協議)本身沒有傳輸包的功能,包的實際傳輸是委托給數據鏈路層(以太網中的交換機)來實現的。
涉及到的三張表分別是
- 交換機中有?MAC 地址表用于映射 MAC 地址和它的端口
- 路由器中有路由表用于映射 IP 地址(段)和它的端口
- 電腦和路由器中都有** arp 緩存表**用于緩存 IP 和 MAC 地址的映射關系
這三張表是怎么來的
- MAC 地址表是通過以太網內各節點之間不斷通過交換機通信,不斷完善起來的。
- 路由表是各種路由算法 + 人工配置逐步完善起來的。
- arp 緩存表是不斷通過 arp 協議的請求逐步完善起來的。
知道了以上這些,目前網絡上兩個節點是如何發送數據包的這個過程,就完全可以解釋通了!
參考的網絡拓撲圖
那接下來我們就放上參考的?最后一個網絡拓撲圖吧,請做好?戰斗?準備!
這時路由器 1 連接了路由器 2,所以其路由表有了下一條地址這一個概念,所以它的路由表就變成了這個樣子。如果匹配到了有下一跳地址的一項,則需要再次匹配,找到其端口,并找到下一跳 IP 的 MAC 地址。
也就是說找來找去,最終必須能映射到一個端口號,然后從這個端口號把數據包發出去。
| 目的地址 | 下一跳 | 端口 |
| 192.168.0.0/24 | 0 | |
| 192.168.0.254/32 | 0 | |
| 192.168.1.0/24 | 1 | |
| 192.168.1.254/32 | 1 | |
| 192.168.2.0/24 | 192.168.100.5 | |
| 192.168.100.0/24 | 2 | |
| 192.168.100.4/32 | 2 |
這時如果 A 給 F 發送一個數據包,能不能通呢?如果通的話整個過程是怎樣的呢?
思考一分鐘...
詳細過程動畫描述:
詳細過程文字描述:
1.?首先 A(192.168.0.1)通過子網掩碼(255.255.255.0)計算出自己與 F(192.168.2.2)并不在同一個子網內,于是決定發送給默認網關(192.168.0.254)
2.?A 通過 ARP 找到 默認網關 192.168.0.254 的 MAC 地址。
3.?A 將源 MAC 地址(AAAA)與網關 MAC 地址(ABAB)封裝在數據鏈路層頭部,又將源 IP 地址(192.168.0.1)和目的 IP 地址(192.168.2.2)(注意這里千萬不要以為填寫的是默認網關的 IP 地址,從始至終這個數據包的兩個 IP 地址都是不變的,只有 MAC 地址在不斷變化)封裝在網絡層頭部,然后發包
4.?交換機 1 收到數據包后,發現目標 MAC 地址是 ABAB,轉發給路由器1
5.?數據包來到了路由器 1,發現其目標 IP 地址是 192.168.2.2,查看其路由表,發現了下一跳的地址是 192.168.100.5*
6.?所以此時路由器 1 需要做兩件事,第一件是再次匹配路由表,發現匹配到了端口為 2,于是將其封裝到數據鏈路層,最后把包從 2 號口發出去。
7.?此時路由器 2 收到了數據包,看到其目的地址是 192.168.2.2,查詢其路由表,匹配到端口號為 1,準備從 1 號口把數據包送出去。
8.?但此時路由器 2 需要知道 192.168.2.2 的 MAC 地址了,于是查看其 arp 緩存,找到其 MAC 地址為 FFFF,將其封裝在數據鏈路層頭部,并從 1 號端口把包發出去。
9.?交換機 3 收到了數據包,發現目的 MAC 地址為 FFFF,查詢其 MAC 地址表,發現應該從其 6 號端口出去,于是從 6 號端口把數據包發出去。
10.F 最終收到了數據包!**并且發現目的 MAC 地址就是自己,于是收下了這個包
HTTP報文傳輸原理
利用TCP/IP進行網絡通信時,數據包會按照分層順序與對方進行通信。發送端從應用層往下走,接收端從鏈路層往上走。從客戶端到服務器的數據,每一幀數據的傳輸的順序都為:應用層->運輸層->網絡層->鏈路層->鏈路層->網絡層->運輸層->應用層。
HTTP報文傳輸過程
以一個HTTP請求的傳輸為例,請求從HTTP客戶端(如瀏覽器)和HTTP服務端應用的傳輸過程,大致如下圖所示:
圖:HTTP請求報文的分層傳輸過程
數據封裝和分用
接下來,為大家介紹一下數據封裝和分用。
數據通過互聯網傳輸的時候不可能是光禿禿的不加標識,如果這樣數據就會亂。所以數據在發送的時候,需要加上特定標識,加上特定標識的過程叫做數據的封裝,在數據使用的時候再去掉特定標識,去掉特定標識的過程就叫做分用。TCP/IP協議的數據封裝和分用過程,大致如下圖所示:
圖:TCP/IP協議的數據封裝和分用過程
在數據封裝時,數據經過每個層都會打上該層特定標識,添加上頭部。
在傳輸層封裝時,添加的報文首部時要存入一個應用程序的標識符,無論TCP和UDP都用一個16位的端口號來表示不同的應用程序,并且都會將源端口和目的端口存入報文首部中。
在網絡層封裝時,IP首部會標識處理數據的協議類型,或者說標識出網絡層數據幀所攜帶的上層數據類型,如TCP、UDP、ICMP、IP、IGMP等等。
具體來說,會在IP首部中存入一個長度為8位的數值,稱作協議域:
1表示為ICMP協議、2表示為IGMP協議、6表示為TCP協議、17表示為UDP協議、等等。IP首部還會標識發送方地址(源IP)和接收方地址(目標IP)。
在鏈路層封裝時,網絡接口分別要發送和接收IP、ARP和RARP等多種不同協議的報文,因此也必須在以太網的幀首部中加入某種形式的標識,以指明所處理的協議類型,為此,以太網的報文幀的首部也有一個16位的類型域,標識出以太網數據幀所攜帶的上層數據類型,如IPv4、ARP、IPV6、PPPoE等等。
數據封裝和分用的過程大致為:發送端每通過一層會增加該層的首部,接收端每通過一層則刪除該層的首部。
總體來說,TCP/IP分層管理、數據封裝和分用的好處:分層之后若需改變相關設計,只需替換變動的層。各層之間的接口部分規劃好之后,每個層次內部的設計就可以自由改動。層次化之后,設計也變得相對簡單:各個層只需考慮分派給自己的傳輸任務。
TCP/IP與OSI的區別主要有哪些呢?除了TCP/IP與OSI在分層模塊上稍有區別,更重要的區別為:OSI參考模型注重“通信協議必要的功能是什么”,而TCP/IP則更強調“在計算機上實現協議應該開發哪種程序”。
實際上,在傳輸過程中,數據報文會在不同的物理網絡之間傳遞,還是以一個HTTP請求的傳輸為例,請求在不同物理網絡之間的傳輸過程,大致如下圖所示:
圖:HTTP請求在不同物理網絡之間的傳輸過程
數據包在不同物理網絡之間的傳輸過程中,網絡層會通過路由器去對不同的網絡之間的數據包進行存儲、分組轉發處理。構造互連網最簡單的方法是把兩個或多個網絡通過路由器進行連接。路由器可以簡單理解為一種特殊的用于網絡互連的硬件盒,其作用是為不同類型的物理網絡提供連接:以太網、令牌環網、點對點的鏈接和FDDI(光纖分布式數據接口)等等。
物理網絡之間通過路由器進行互連,隨著增加不同類型的物理網絡,可能會有很多個路由器,但是對于應用層來說仍然是一樣的,TCP協議棧為大家屏蔽了物理層的復雜性??傊?#xff0c;物理細節和差異性的隱藏,使得互聯網TCP/IP傳輸的功能變得非常強大。
接下來,開始為大家介紹與傳輸性能有密切關系的內容:TCP傳輸層的三次握手建立連接,四次揮手釋放連接。不過在此之前,還得先介紹一下TCP報文協議。
TCP協議的報文格式
在TCP/IP協議棧中,IP協議層只關心如何使數據能夠跨越本地網絡邊界的問題,而不關心數據如何傳輸。整體TCP/IP協議棧,共同配合一起解決數據如何通過許許多多個點對點通路,順利傳輸到達目的地。一個點對點通路被稱為一“跳”(hop),通過TCP/IP協議棧,網絡成員能夠在許多“跳”的基礎上建立相互的數據通路。
傳輸層TCP協議提供了一種面向連接的、可靠的字節流服務,其數據幀格式,大致如下圖所示:
圖:傳輸層TCP協議的數據幀格式
一個傳輸層TCP協議的數據幀,大致包含以下字段:
(一)源端口號
源端口號表示報文的發送端口,占16位。源端口和源IP地址組合起來,可以標識報文的發送地址。
(二)目的端口號
目的端口號表示報文的接收端口,占16位。目的端口和目的IP地址相結合,可以標識報文的接收地址。
TCP協議是基于IP協議的基礎上傳輸的,TCP報文中的源端口號+源IP,與TCP報文中的目的端口號+目的IP一起,組合起來唯一性的確定一條TCP連接。
(三)序號(Sequence Number)
TCP傳輸過程中,在發送端出的字節流中,傳輸報文中的數據部分的每一個字節都有它的編號。序號(Sequence
Number)占32位,發起方發送數據時,都需要標記序號。
序號(Sequence Number)的語義與SYN控制標志(Control
Bits)的值有關。根據控制標志(Control Bits)中的SYN是否為1,序號(Sequence
Number)表達不同的含義:
(1)當SYN = 1時,當前為連接建立階段,此時的序號為初始序號ISN((Initial Sequence
Number),通過算法來隨機生成序號;
(2)當SYN = 0時在數據傳輸正式開始時,第一個報文的序號為 ISN +
1,后面的報文的序號,為前一個報文的SN值+TCP報文的凈荷字節數(不包含TCP頭)。比如,如果發送端發送的一個TCP幀的凈荷為12byte,序號為5,則發送端接著發送的下一個數據包的時候,序號的值應該設置為5+12=17。
在數據傳輸過程中,TCP協議通過序號(Sequence
Number)對上層提供有序的數據流。發送端可以用序號來跟蹤發送的數據量;接收端可以用序號識別出重復接收到的TCP包,從而丟棄重復包;對于亂序的數據包,接收端也可以依靠序號對其進行排序。
(四)確認序號(Acknowledgment Number)
確認序號(Acknowledgment
Number)標識了報文接收端期望接收的字節序列。如果設置了ACK控制位,確認序號的值表示一個準備接收的包的序列碼,注意,它所指向的是準備接收的包,也就是下一個期望接收的包的序列碼。
舉個例子,假設發送端(如Client)發送3個凈荷為1000byte、起始SN序號為1的數據包給Server服務端,Server每收到一個包之后,需要回復一個ACK響應確認數據包給Client。ACK響應數據包的ACK
Number值,為每個Client包的為SN+包凈荷,既表示Server已經確認收到的字節數,還表示期望接收到的下一個Client發送包的SN序號,具體的ACK值如下圖左邊的正常傳輸部分所示。
圖:傳輸過程的確認序號(Acknowledgment Number)值示例圖
在上圖的左邊部分,Server第1個ACK包的ACK
Number值為1001,是通過Client第1個包的SN+包凈荷=1+1000計算得到,表示期望第2個Client包的SN序號為1001;Server第2個ACK包的ACK
Number值為2001,為Client第2個包的SN+包凈荷=2001,表示期望第3個Server包的SN為2001,以此類推。
如果發生錯誤,假設Server在處理Client的第二個發送包異常,Server仍然回復一個ACK
Number值為1001的確認包,則Client的第二個數據包需要重復發送,具體的ACK值如上圖右邊的正常傳輸部分所示。
只有控制標志的ACK標志為1時,數據幀中的確認序號ACK
Number才有效。TCP協議規定,連接建立后,所有發送的報文的ACK必須為1,也就是建立連接后,所有報文的確認序號有效。如果是SYN類型的報文,其ACK標志為0,故沒有確認序號。
(五)頭部長度
該字段占用4位,用來表示TCP報文首部的長度,單位是4bit位。其值所表示的并不是字節數,而是頭部的所含有的32bit的數目(或者倍數),或者4個字節的倍數,所以TCP頭部最多可以有60字節(4*15=60)。沒有任何選項字段的TCP頭部長度為20字節,所以其頭部長度為5,可以通過20/4=5計算得到。
(六)預留6位
頭部長度后面預留的字段長度為6位,作為保留字段,暫時沒有什么用處。
(七)控制標志
控制標志(Control
Bits)共6個bit位,具體的標志位為:URG、ACK、PSH、RST、SYN、FIN。6個標志位的說明,如下表所示。
表:TCP報文控制標志(Control Bits)說明
| 標志位 | 說明 |
| URG | 占1位,表示緊急指針字段有效。URG位指示報文段里的上層實體(數據)標記為“緊急”數據。當URG=1時,其后的緊急指針指示緊急數據在當前數據段中的位置(相對于當前序列號的字節偏移量),TCP接收方必須通知上層實體。 |
| ACK | 占1位,置位ACK=1表示確認號字段有效;TCP協議規定,接建立后所有發送的報文的ACK必須為1;當ACK=0時,表示該數據段不包含確認信息。當ACK=1時,表示該報文段包括一個對已被成功接收報文段的確認序號Acknowledgment Number,該序號同時也是下一個報文的預期序號。 |
| PSH | 占1位,表示當前報文需要請求推(push)操作;當PSH=1時,接收方在收到數據后立即將數據交給上層,而不是直到整個緩沖區滿。 |
| RST | 占1位,置位RST=1表示復位TCP連接;用于重置一個已經混亂的連接,也可用于拒絕一個無效的數據段或者拒絕一個連接請求。如果數據段被設置了RST位,說明報文發送方有問題發生。 |
| SYN | 占1位,在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連接請求報文。對方若同意建立連接,則應在響應報文中使SYN=1和ACK=1。 綜合一下,SYN置1就表示這是一個連接請求或連接接受報文。 |
| FIN | 占1位,用于在釋放TCP連接時,標識發送方比特流結束,用來釋放一個連接。當 FIN = 1時,表明此報文的發送方的數據已經發送完畢,并要求釋放連接。 |
在連接建立的三次握手過程中,若只是單個SYN置位,表示的只是建立連接請求。如果SYN和ACK同時置位為1,表示的建立連接之后的響應。
(八)窗口大小:
長度為16位,共2個字節。此字段用來進行流量控制。流量控制的單位為字節數,這個值是本端期望一次接收的字節數。
(九)校驗和:
長度為16位,共2個字節。對整個TCP報文段,即TCP頭部和TCP數據進行校驗和計算,接收端用于對收到的數據包進行驗證。
(十)緊急指針:
長度為16米,2個字節。它是一個偏移量,和SN序號值相加表示緊急數據最后一個字節的序號。
以上十項內容是TCP報文首部必須的字段,也稱固有字段,長度為20個字節。接下來是TCP報文的可選項和填充部分。
(十一)可選項和填充部分
可選項和填充部分的長度為4n字節(n是整數),該部分是根據需要而增加的選項。如果不足4n字節,要加填充位,使得選項長度為32位(4字節)的整數倍,具體的做法是在這個字段中加入額外的零,以確保TCP頭是32位(4字節)的整數倍。
最常見的選項字段是MSS(Maximum Segment
Size最長報文大小),每個連接方通常都在通信的第一個報文段(SYN標志為1的那個段)中指明這個選項字段,表示當前連接方所能接受的最大報文段的長度。
由于可選項和填充部分不是必須的,所以TCP報文首部最小長度為20個字節。
至此,TCP報文首部的字段,就全部介紹完了。TCP報文首部的后面,接著的是數據部分,不過數據部分是可選的。在一個連接建立和一個連接終止時,雙方交換的報文段僅有TCP首部。如果一方沒有數據要發送,也使用沒有任何數據的首部來確認收到的數據,比如在處理超時的過程中,也會發送不帶任何數據的報文段。
總體來說,TCP協議的可靠性,主要通過以下幾點來保障:
(1)應用數據分割成TCP認為最適合發送的數據塊。這部分是通過MSS(最大數據包長度)選項來控制的,通常這種機制也被稱為一種協商機制,MSS規定了TCP傳往另一端的最大數據塊的長度。值得注意的是,MSS只能出現在SYN報文段中,若一方不接收來自另一方的MSS值,則MSS就定為536字節。一般來講,MSS值還是越大越好,這樣可以提高網絡的利用率。
(2)重傳機制。設置定時器,等待確認包,如果定時器超時還沒有收到確認包,則報文重傳。
(3)對首部和數據進行校驗。
(4)接收端對收到的數據進行排序,然后交給應用層。
(5)接收端丟棄重復的數據。
(6)TCP還提供流量控制,主要是通過滑動窗口來實現流量控制。
至此TCP協議的數據幀格式介紹完了。接下來開始為大家重點介紹:TCP傳輸層的三次握手建立連接,四次揮手釋放連接。
TCP的三次握手
TCP連接的建立時,雙方需要經過三次握手,而斷開連接時,雙方需要經過四次分手,那么,其三次握手和四次分手分別做了什么呢?又是如何進行的呢?
通常情況下,建立連接的雙方,由一端打開一個監聽套接字(ServerSocket)來監聽來自請求方的TCP(Socket)連接,當服務器端監聽開始時,必須做好準備接受外來的連接,在Java中該操作通過創建一個ServerSocket服務監聽套接字實例來完成,此操作會調用底層操作系統(如Linux)的C代碼中三個函數socket()、bind()、listen()
來完成。開始監聽之后,服務器端就做好接受外來連接的準備,如果監聽到建立新連接的請求,會開啟一個傳輸套接字,稱之為被動打開(Passive
Open)。
一段簡單的服務端監聽新連接請求,并且被動打開(Passive
Open)傳輸套接字的Java示例代碼,具體如下:
客戶端在發起連接建立時,Java代碼通過創建Socket實例,調用底層的connect(…)方法,主動打開(Active
Open)Socket連接。套接字監聽方在收到請求之后,監聽方和發起方(客戶端)之間就會建立一條的連接通道,該通道由雙方IP和雙方端口所唯一確定。
一段簡單的客戶端連接主動打開(Active Open)的Java示例代碼,具體如下:
public class SocketClient {public static void main(String[] args) throws InterruptedException {try {// 和服務器創建連接Socket socket = new Socket("localhost",8080);// 寫入給監聽方的輸出流OutputStream os = socket.getOutputStream();…..// 讀取監聽方的輸入流InputStream is = socket.getInputStream();…..} catch (Exception e) {e.printStackTrace();}}}三次握手過程
TCP連接的建立時,雙方需要經過三次握手,具體過程如下:
(1)第一次握手:Client進入SYN_SENT狀態,發送一個SYN幀來主動打開傳輸通道,該幀的SYN標志位被設置為1,同時會帶上Client分配好的SN序列號,該SN是根據時間產生的一個隨機值,通常情況下每間隔4ms會加1。除此之外,SYN幀還會帶一個MSS(最大報文段長度)可選項的值,表示客戶端發送出去的最大數據塊的長度。
(2)第二次握手:Server端在收到SYN幀之后,會進入SYN_RCVD狀態,同時返回SYN+ACK幀給Client,主要目的在于通知Client,Server端已經收到SYN消息,現在需要進行確認。Server端發出的SYN+ACK幀的ACK標志位被設置為1,其確認序號AN(Acknowledgment
Number)值被設置為Client的SN+1;SYN+ACK幀的SYN標志位被設置為1,SN值為Server端生成的SN序號;SYN+ACK幀的MSS(最大報文段長度)表示的是Server端的最大數據塊長度。
(3)第三次握手:Client在收到Server的第二次握手SYN+ACK確認幀之后,首先將自己的狀態會從SYN_SENT變成ESTABLISHED,表示自己方向的連接通道已經建立成功,Client可以發送數據給Server端了。然后,Client發ACK幀給Server端,該ACK幀的ACK標志位被設置為1,其確認序號AN(Acknowledgment
Number)值被設置為Server端的SN序列號+1。還有一種情況,Client可能會將ACK幀和第一幀要發送的數據,合并到一起發送給Server端。
(4)Server端在收到Client的ACK幀之后,會從SYN_RCVD狀態會進入ESTABLISHED狀態,至此,Server方向的通道連接建立成功,Server可以發送數據給Client,TCP的全雙工連接建立完成。
三次握手的圖解
三次握手的交互過程,具體如下圖所示:
圖:TCP建立的連接時三次握手示意圖
Client和Server完成了三次握手后,雙方就進入了數據傳輸的階段。數據傳輸完成后,連接將斷開,連接斷開的過程需要經歷四次揮手。
TCP的四次揮手
業務數據通信完成之后,TCP連接開始斷開(或者拆接)的過程,在這個過程中連接的每個端的都能獨立地、主動的發起,斷開的過程TCP協議使用了四路揮手操作。
四次揮手具體過程
四次揮手具體過程,具體如下:
(1)第一次揮手:主動斷開方(可以是客戶端,也可以是服務器端),向對方發送一個FIN結束請求報文,此報文的FIN位被設置為1,并且正確設置Sequence
Number(序列號)和Acknowledgment
Number(確認號)。發送完成后,主動斷開方進入FIN_WAIT_1狀態,這表示主動斷開方沒有業務數據要發送給對方,準備關閉SOCKET連接了。
(2)第二次揮手:正常情況下,在收到了主動斷開方發送的FIN斷開請求報文后,被動斷開方會發送一個ACK響應報文,報文的Acknowledgment
Number(確認號)值為斷開請求報文的Sequence Number
(序列號)加1,該ACK確認報文的含義是:“我同意你的連接斷開請求”。之后,被動斷開方就進入了CLOSE-WAIT(關閉等待)狀態,TCP協議服務會通知高層的應用進程,對方向本地方向的連接已經關閉,對方已經沒有數據要發送了,若本地還要發送數據給對方,對方依然會接受。被動斷開方的CLOSE-WAIT(關閉等待)還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
主動斷開方在收到了ACK報文后,由FIN_WAIT_1轉換成FIN_WAIT_2狀態。
(3)第三次揮手:在發送完成ACK報文后,被動斷開方還可以繼續完成業務數據的發送,待剩余數據發送完成后,或者CLOSE-WAIT(關閉等待)截止后,被動斷開方會向主動斷開方發送一個FIN+ACK結束響應報文,表示被動斷開方的數據都發送完了,然后,被動斷開方進入LAST_ACK狀態。
(4)第四次揮手:主動斷開方收在到FIN+ACK斷開響應報文后,還需要進行最后的確認,向被動斷開方發送一個ACK確認報文,然后,自己就進入TIME_WAIT狀態,等待超時后最終關閉連接。處于TIME_WAIT狀態的主動斷開方,在等待完成2MSL的時間后,如果期間沒有收到其他報文,則證明對方已正常關閉,主動斷開方的連接最終關閉。
被動斷開方在收到主動斷開方的最后的ACK報文以后,最終關閉了連接,自己啥也不管了。
四次揮手圖解
四次揮手的全部交互過程,具體如下圖所示:
圖:TCP建立的連接時四次揮手的示意圖
處于TIME_WAIT狀態的主動斷開方,在等待完成2MSL的時間后,才真正關閉連接通道,其等待的時間為什么是2MSL呢?
2MSL翻譯過來就是兩倍的MSL。MSL全稱為Maximum Segment
Lifetime,指的是一個TCP報文片段在網絡中最大的存活時間,具體來說,2MSL對應于一次消息的來回(一個發送和一個回復)所需的最大時間。如果直到2MSL,主動斷開方都沒有再一次收到對方的報文(如FIN報文),則可以推斷ACK已經被對方成功接收,此時,主動斷開方將最終結束自己的TCP連接。所以,TCP的TIME_WAIT狀態也稱為2MSL等待狀態。
有關MSL的具體的時間長度,在RFC1122協議中推薦為2分鐘。在SICS(瑞典計算機科學院)開發的一個小型開源的TCP/IP協議?!狶wIP開源協議棧中MSL默認為1分鐘。在源自Berkeley的TCP協議棧實現中MSL默認長度為30秒??傮w來說,TIME_WAIT(2MSL)等待狀態的時間長度,一般維持在1-4分鐘之間。
通過三次握手建立連接和四次揮手拆除連接,一次TCP的連接建立及拆除,至少進行7次通信,可見其成本是很高的。
三次握手、四次揮手的常見面試題
有關TCP的連接建立的三次握手及拆除過程的四次揮手的面試問題,是技術面試過程中的出現頻率很高的重點和難點問題,常見問題大致如下:
問題(1):為什么關閉連接的需要四次揮手,而建立連接卻只要三次握手呢?
關閉連接時,被動斷開方在收到對方的FIN結束請求報文時,很可能業務數據沒有發送完成,并不能立即關閉連接,被動方只能先回復一個ACK響應報文,告訴主動斷開方:“你發的FIN報文我收到了,只有等到我所有的業務報文都發送完了,我才能真正的結束,在結束之前,我會發你FIN+ACK報文的,你先等著”。所以,被動斷開方的確認報文,需要拆開成為兩步,故總體就需要四步揮手。
而在建立連接場景中,Server端的應答可以稍微簡單一些。當Server端收到Client端的SYN連接請求報文后,其中ACK報文表示對請求報文的應答,SYN報文用來表示服務端的連接也已經同步開啟了,而ACK報文和SYN報文之間,不會有其他報文需要發送,故而可以合二為一,可以直接發送一個SYN+ACK報文。所以,在建立連接時,只需要三次握手即可。
問題(2):為什么連接建立的時候是三次握手,可以改成兩次握手嗎?
三次握手完成兩個重要的功能:一是雙方都做好發送數據的準備工作,而且雙方都知道對方已準備好;二是雙方完成初始SN序列號的協商,雙方的SN序列號在握手過程中被發送和確認。
如果把三次握手改成兩次握手,可能發生死鎖。兩次握手的話,缺失了Client的二次確認ACK幀,假想的TCP建立的連接時二次揮手,可以如下圖所示:
圖:假想的TCP建立的連接時二次握手的示意圖
在假想的TCP建立的連接時二次握手過程中,Client發送Server發送一個SYN請求幀,Server收到后發送了確認應答SYN+ACK幀。按照兩次握手的協定,Server認為連接已經成功地建立了,可以開始發送數據幀。這個過程中,如果確認應答SYN+ACK幀在傳輸中被丟失,Client沒有收到,Client將不知道Server是否已準備好,也不知道Server的SN序列號,Client認為連接還未建立成功,將忽略Server發來的任何數據分組,會一直等待Server的SYN+ACK確認應答幀。而Server在發出的數據幀后,一直沒有收到對應的ACK確認后就會產生超時,重復發送同樣的數據幀。這樣就形成了死鎖。
問題(3):為什么主動斷開方在TIME-WAIT狀態必須等待2MSL的時間?
原因之一:主動斷開方等待2MSL的時間,是為了確保兩端都能最終關閉。假設網絡是不可靠的,被動斷開方發送FIN+ACK報文后,其主動方的ACK響應報文有可能丟失,這時候的被動斷開方處于LAST-ACK狀態的,由于收不到ACK確認被動方一直不能正常的進入CLOSED狀態。在這種場景下,被動斷開方會超時重傳FIN+ACK斷開響應報文,如果主動斷開方在2MSL時間內,收到這個重傳的FIN+ACK報文,會重傳一次ACK報文,后再一次重新啟動2MSL計時等待,這樣,就能確保被動斷開方能收到ACK報文,從而能確保被動方順利進入到CLOSED狀態。只有這樣,雙方都能夠確保關閉。反過來說,如果主動斷開方在發送完ACK響應報文后,不是進入TIME_WAIT狀態去等待2MSL時間,而是立即釋放連接,則將無法收到被動方重傳的FIN+ACK報文,所以不會再發送一次ACK確認報文,此時處于LAST-ACK狀態的被動斷開方,無法正常進入到CLOSED狀態。
原因之二:防止“舊連接的已失效的數據報文”出現在新連接中。主動斷開方在發送完最后一個ACK報文后,再經過2MSL,才能最終關閉和釋放端口,這就意味著,相同端口的新TCP新連接,需要在2MSL的時間之后,才能夠正常的建立。2MSL這段時間內,舊連接所產生的所有數據報文,都已經從網絡中消失了,從而,確保了下一個新的連接中不會出現這種舊連接請求報文。
問題(4):如果已經建立了連接,但是Client端突然出現故障了怎么辦?
TCP還設有一個保活計時器,Client端如果出現故障,Server端不能一直等下去,這樣會浪費系統資源。每收到一次Client客戶端的數據幀后,Server端都的?;钣嫊r器會復位。計時器的超時時間通常是設置為2小時,若2小時還沒有收到Client端的任何數據幀,Server端就會發送一個探測報文段,以后每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,Server端就認為Client端出了故障,接著就關閉連接。如果覺得?;钣嫊r器的兩個多小時的間隔太長,可以自行調整TCP連接的保活參數。
總結
以上是生活随笔為你收集整理的太棒了!TCP/IP协议 (图解+秒懂+史上最全)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx修改upstream不重启的方
- 下一篇: 开始学习jQuery和准备工作