Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 506, comments - 13, trackbacks - 0, articles - 1

          本文引用了公眾號純潔的微笑作者奎哥的技術文章,感謝原作者的分享。

          1、前言

          老于網絡編程熟手來說,在測試和部署網絡通信應用(比如IM聊天、實時音視頻等)時,如果發現網絡連接超時,第一時間想到的就是使用Ping命令Ping一下服務器看看通不通。甚至在有些情況下通過圖形化的Ping命令工具對目標網絡進行長測(比如:《兩款增強型Ping工具:持續統計、圖形化展式網絡狀況 [附件下載]》、《網絡測試:Android版多路ping命令工具EnterprisePing[附件下載]》),可以得出當前網絡通信的網絡延遲、網絡丟包率、網絡抖動等等有價值信息。

          Ping命令很簡單,但作為為數不多的網絡檢測工具,卻非常有用,是開發網絡應用時最常用到的命令。雖然“Ping”這個動作這么簡單,但你知道Ping命令背后后的邏輯嗎?這就是本文要告訴你!

          學習交流:

          - 即時通訊開發交流3群:185926912 [推薦]

          - 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM

          (本文同步發布于:http://www.52im.net/thread-1973-1-1.html

          2、系列文章

          本文是系列文章中的第5篇,本系列大綱如下:

          腦殘式網絡編程入門(一):跟著動畫來學TCP三次握手和四次揮手

          腦殘式網絡編程入門(二):我們在讀寫Socket時,究竟在讀寫什么?

          腦殘式網絡編程入門(三):HTTP協議必知必會的一些知識

          腦殘式網絡編程入門(四):快速理解HTTP/2的服務器推送(Server Push)

          腦殘式網絡編程入門(五):每天都在用的Ping命令,它到底是什么?》(本文)

          3、Ping命令的作用和原理

          簡單來說,「ping」是用來探測本機與網絡中另一主機之間是否可達的命令,如果兩臺主機之間ping不通,則表明這兩臺主機不能建立起連接。ping是定位網絡通不通的一個重要手段。

          ping 命令是基于 ICMP 協議來工作的,「 ICMP 」全稱為 Internet 控制報文協議(Internet Control Message Protocol)。ping 命令會發送一份ICMP回顯請求報文給目標主機,并等待目標主機返回ICMP回顯應答。因為ICMP協議會要求目標主機在收到消息之后,必須返回ICMP應答消息給源主機,如果源主機在一定時間內收到了目標主機的應答,則表明兩臺主機之間網絡是可達的。

          舉一個例子來描述「ping」命令的工作過程:

          1)假設有兩個主機,主機A(192.168.0.1)和主機B(192.168.0.2),現在我們要監測主機A和主機B之間網絡是否可達,那么我們在主機A上輸入命令:ping 192.168.0.2;

          2)此時,ping命令會在主機A上構建一個 ICMP的請求數據包(數據包里的內容后面再詳述),然后 ICMP協議會將這個數據包以及目標IP(192.168.0.2)等信息一同交給IP層協議;

          3)IP層協議得到這些信息后,將源地址(即本機IP)、目標地址(即目標IP:192.168.0.2)、再加上一些其它的控制信息,構建成一個IP數據包;

          4)IP數據包構建完成后,還不夠,還需要加上MAC地址,因此,還需要通過ARP映射表找出目標IP所對應的MAC地址。當拿到了目標主機的MAC地址和本機MAC后,一并交給數據鏈路層,組裝成一個數據幀,依據以太網的介質訪問規則,將它們傳送出出去;

          5)當主機B收到這個數據幀之后,會首先檢查它的目標MAC地址是不是本機,如果是就接收下來處理,接收之后會檢查這個數據幀,將數據幀中的IP數據包取出來,交給本機的IP層協議,然后IP層協議檢查完之后,再將ICMP數據包取出來交給ICMP協議處理,當這一步也處理完成之后,就會構建一個ICMP應答數據包,回發給主機A;

          6)在一定的時間內,如果主機A收到了應答包,則說明它與主機B之間網絡可達,如果沒有收到,則說明網絡不可達。除了監測是否可達以外,還可以利用應答時間和發起時間之間的差值,計算出數據包的延遲耗時。

          通過ping的流程可以發現,ICMP協議是這個過程的基礎,是非常重要的,下面的章節會把ICMP協議再詳細解釋一下,請繼續往下讀。

          4、正確理解ICMP協議

          Ping命令所基于的ICMP協議所處的網絡模型層級:

          (▲ 上圖來自《計算機網絡通訊協議關系圖(中文珍藏版)[附件下載]》,您可下載此圖的完整清晰版)

          Ping命令這么簡單,在任何系統上上手就能使用,很多人可能想當然的認為Ping命令使用的ICMP協議應該是基于傳輸層的TCP或UDP協議的吧。

          正如上圖所示,ICMP協議既不是基于TCP,也不是基于UDP,而是直接基于網絡層的IP協議,在整個網絡協議棧中屬于相當底層的協議了。這也從側面證明了它的重要性,因為根據ICMP的RFC手冊規定:ICMP協議是任何支持IP協議的系統必須實現的,沒有余地。而IP協議是整個互聯網的基石,ICMP協議雖簡單,但重要性不言而喻。

          所以,以后面視的時候,如果碰到“ICMP協議是基于什么實現的?”這樣的問題,請一定要記往此節所講的內容。

          5、深入ICMP協議

          我們知道,ping命令是基于ICMP協議來實現的。那么我們再來看下圖,就明白了ICMP協議又是通過IP協議來發送的,即ICMP報文是封裝在IP包中(如下圖所示)。

          IP協議是一種無連接的,不可靠的數據包協議,它并不能保證數據一定被送達,那么我們要保證數據送到就需要通過其它模塊來協助實現,這里就引入的是ICMP協議。

          當傳送的IP數據包發送異常的時候,ICMP就會將異常信息封裝在包內,然后回傳給源主機。

          將上圖再細拆一下可見:

          繼續將ICMP協議模塊細拆:

          由圖可知,ICMP數據包由8bit的類型字段和8bit的代碼字段以及16bit的校驗字段再加上選項數據組成。

          ICMP協議大致可分為兩類:

          1)查詢報文類型;

          2)差錯報文類型。

          【關于查詢報文類型】:

          查詢報文主要應用于:ping查詢、子網掩碼查詢、時間戳查詢等等。

          上面講到的ping命令的流程其實就對應ICMP協議查詢報文類型的一種使用。在主機A構建ICMP請求數據包的時候,其ICMP的類型字段中使用的是 8 (回送請求),當主機B構建ICMP應答包的時候,其ICMP類型字段就使用的是 0 (回送應答),更多類型值參考上表。

          對 查詢報文類型 的理解可參考一下文章最開始講的ping流程,這里就不做贅述。

          【關于差錯報文類型】:

          差錯報文主要產生于當數據傳送發送錯誤的時候。

          它包括:目標不可達(網絡不可達、主機不可達、協議不可達、端口不可達、禁止分片等)、超時、參數問題、重定向(網絡重定向、主機重定向等)等等。

          差錯報文通常包含了引起錯誤的IP數據包的第一個分片的IP首部,加上該分片數據部分的前8個字節。

          當傳送IP數據包發生錯誤的時候(例如 主機不可達),ICMP協議就會把錯誤信息封包,然后傳送回源主機,那么源主機就知道該怎么處理了。

          6、ICMP差錯報文的妙用

          正如上一節所介紹的那樣,ICMP協議主要有:查詢報文類型和差錯報文類型兩種。對于差錯報文來說,是不是只有遇到錯誤的時候才能使用呢?不是!

          基于這個特性,Linux下的Traceroute指令(Windows下的對等指令是tracert)利于ICMP的差錯報文可以實現遍歷到數據包傳輸路徑上的所有路由器!這真是個有用的命令!

          百度百科上關于traceroute命令的用途:

          traceroute (Windows 系統下是tracert) 命令利用ICMP 協議定位您的計算機和目標計算機之間的所有路由器。TTL 值可以反映數據包經過的路由器或網關的數量,通過操縱獨立ICMP 呼叫報文的TTL 值和觀察該報文被拋棄的返回信息,traceroute命令能夠遍歷到數據包傳輸路徑上的所有路由器。

          ICMP的差錯報文的使用,使得Traceroute成為用來偵測源主機到目標主機之間所經過路由情況的常用工具。Traceroute 的原理就是利用ICMP的規則,制造一些錯誤的事件出來,然后根據錯誤的事件來評估網絡路由情況。

          traceroute的基本原理如下圖所示:

          具體做法就是:

          1)Traceroute會設置特殊的TTL值,來追蹤源主機和目標主機之間的路由數。首先它給目標主機發送一個 TTL=1 的UDP數據包,那么這個數據包一旦在路上遇到一個路由器,TTL就變成了0(TTL規則是每經過一個路由器都會減1),因為TTL=0了,所以路由器就會把這個數據包丟掉,然后產生一個錯誤類型(超時)的ICMP數據包回發給源主機,也就是差錯包。這個時候源主機就拿到了第一個路由節點的IP和相關信息了;

          2)接著,源主機再給目標主機發一個 TTL=2 的UDP數據包,依舊上述流程走一遍,就知道第二個路由節點的IP和耗時情況等信息了;

          3)如此反復進行,Traceroute就可以拿到從主機A到主機B之間所有路由器的信息了。

          但是有個問題是,如果數據包到達了目標主機的話,即使目標主機接收到TTL值為1的IP數據包,它也是不會丟棄該數據包的,也不會產生一份超時的ICMP回發數據包的,因為數據包已經達到了目的地嘛。那我們應該怎么認定數據包是否達到了目標主機呢?

          Traceroute的方法是在源主機發送UDP數據包給目標主機的時候,會設置一個不可能達到的目標端口號(例如大于30000的端口號),那么當這個數據包真的到達目標主機的時候,目標主機發現沒有對應的端口號,因此會產生一份“端口不可達”的錯誤ICMP報文返回給源主機。

          可見Traceroute的原理確實很取巧,很有趣。如您對Traceroute感興趣,可以深入讀一讀《從Traceroute看網絡問題》一文。

          附錄:更多網絡編程精華文章

          TCP/IP詳解 - 第11章·UDP:用戶數據報協議

          TCP/IP詳解 - 第17章·TCP:傳輸控制協議

          TCP/IP詳解 - 第18章·TCP連接的建立與終止

          TCP/IP詳解 - 第21章·TCP的超時與重傳

          技術往事:改變世界的TCP/IP協議(珍貴多圖、手機慎點)

          通俗易懂-深入理解TCP協議(上):理論基礎

          通俗易懂-深入理解TCP協議(下):RTT、滑動窗口、擁塞處理

          理論經典:TCP協議的3次握手與4次揮手過程詳解

          理論聯系實際:Wireshark抓包分析TCP 3次握手、4次揮手過程

          計算機網絡通訊協議關系圖(中文珍藏版)

          UDP中一個包的大小最大能多大?

          P2P技術詳解(一):NAT詳解——詳細原理、P2P簡介

          P2P技術詳解(二):P2P中的NAT穿越(打洞)方案詳解

          P2P技術詳解(三):P2P技術之STUN、TURN、ICE詳解

          通俗易懂:快速理解P2P技術中的NAT穿透原理

          高性能網絡編程(一):單臺服務器并發TCP連接數到底可以有多少

          高性能網絡編程(二):上一個10年,著名的C10K并發連接問題

          高性能網絡編程(三):下一個10年,是時候考慮C10M并發問題了

          高性能網絡編程(四):從C10K到C10M高性能網絡應用的理論探索

          高性能網絡編程(五):一文讀懂高性能網絡編程中的I/O模型

          高性能網絡編程(六):一文讀懂高性能網絡編程中的線程模型

          不為人知的網絡編程(一):淺析TCP協議中的疑難雜癥(上篇)

          不為人知的網絡編程(二):淺析TCP協議中的疑難雜癥(下篇)

          不為人知的網絡編程(三):關閉TCP連接時為什么會TIME_WAIT、CLOSE_WAIT

          不為人知的網絡編程(四):深入研究分析TCP的異常關閉

          不為人知的網絡編程(五):UDP的連接性和負載均衡

          不為人知的網絡編程(六):深入地理解UDP協議并用好它

          不為人知的網絡編程(七):如何讓不可靠的UDP變的可靠?

          網絡編程懶人入門(一):快速理解網絡通信協議(上篇)

          網絡編程懶人入門(二):快速理解網絡通信協議(下篇)

          網絡編程懶人入門(三):快速理解TCP協議一篇就夠

          網絡編程懶人入門(四):快速理解TCP和UDP的差異

          網絡編程懶人入門(五):快速理解為什么說UDP有時比TCP更有優勢

          網絡編程懶人入門(六):史上最通俗的集線器、交換機、路由器功能原理入門

          網絡編程懶人入門(七):深入淺出,全面理解HTTP協議

          網絡編程懶人入門(八):手把手教你寫基于TCP的Socket長連接

          技術掃盲:新一代基于UDP的低延時網絡傳輸層協議——QUIC詳解

          讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享

          現代移動端網絡短連接的優化手段總結:請求速度、弱網適應、安全保障

          聊聊iOS中網絡編程長連接的那些事

          移動端IM開發者必讀(一):通俗易懂,理解移動網絡的“弱”和“慢”

          移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結

          IPv6技術詳解:基本概念、應用現狀、技術實踐(上篇)

          IPv6技術詳解:基本概念、應用現狀、技術實踐(下篇)

          從HTTP/0.9到HTTP/2:一文讀懂HTTP協議的歷史演變和設計思路

          以網游服務端的網絡接入層設計為例,理解實時通信的技術挑戰

          邁向高階:優秀Android程序員必知必會的網絡基礎

          >> 更多同類文章 ……

          (本文同步發布于:http://www.52im.net/thread-1973-1-1.html



          作者:Jack Jiang (點擊作者姓名進入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時通訊開發交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時是【原創Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 石首市| 墨玉县| 新密市| 乌兰浩特市| 泸水县| 红安县| 高雄县| 竹山县| 凤冈县| 西城区| 镇赉县| 茂名市| 汾西县| 金华市| 大竹县| 娄底市| 弥渡县| 常德市| 玉林市| 铅山县| 乌兰察布市| 成安县| 迁西县| 盐亭县| 鹤壁市| 扎鲁特旗| 闸北区| 两当县| 普宁市| 浮山县| 红安县| 墨脱县| 锡林浩特市| 库伦旗| 城固县| 区。| 长治县| 陈巴尔虎旗| 治县。| 蕉岭县| 双流县|