首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

利用 ICMP 協議實現路由追蹤:原理與 VC++ 實戰

     編輯:關於VC++

在網際網路中,資料封包從來源主機傳遞至目的主機,必須經由多個路由器轉發。每台路由器內部都維護一張路由表,根據目的 IP 位址決定下一跳。然而,網路拓撲會隨時變動,兩台主機之間並無固定路徑。若要掌握封包實際經過的路由節點,就需要進行「路由追蹤」。本文將詳細介紹如何利用 ICMP 協議的 TTL 機制,在 Visual C++ 6.0 環境下實作一個路由追蹤工具。

一、ICMP 協議基礎

ICMP(Internet Control Message Protocol,網際網路控制訊息協議)是 IP 層的輔助協議,主要用於回報錯誤、交換控制訊息。ICMP 封包封裝在 IP 資料報的資料部分,再由資料鏈路層幀封裝傳輸。ICMP 封包頭部包含三個關鍵欄位:類型、代碼、檢驗和。常見類型包括:

  • 類型 8:回應請求
  • 類型 0:回應應答
  • 類型 3:目的不可達
  • 類型 11:TTL 超時

當 IP 封包的 TTL(Time To Live)在經過每個路由器時遞減至 0,該路由器會丟棄封包,並向來源主機發送一個「TTL 超時」ICMP 訊息(類型 11),其 IP 來源位址即為該路由器位址。這正是路由追蹤的核心原理。

ICMP 封包封裝示意圖

圖 1:ICMP 封包的封裝結構

二、路由追蹤實作原理

追蹤流程如下:

  1. 來源主機發送 TTL=1 的 ICMP 回應請求封包(類型 8)。
  2. 第一個路由器收到後將 TTL 減為 0,丟棄封包並回傳 TTL 超時訊息(類型 11),來源主機由此獲得第一跳路由器 IP。
  3. 來源主機接著發送 TTL=2、3… 的封包,依序獲得後續路由器位址。
  4. 直到收到目的主機的回應應答(類型 0)或目的不可達(類型 3),或達到最大跳數上限。

關鍵在於動態設定 Socket 的 TTL 值,使用 setsockopt(m_Sock, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int)) 即可實現。

路由追蹤流程圖

圖 2:路由追蹤流程圖

三、VC++ 程式實作步驟

1. 專案建立與環境設定

  • 建立基於對話框的 MFC AppWizard 專案,命名為 RouteTrace。
  • 在 stdafx.h 中加入 #include "winsock2.h"。
  • 專案屬性 → Link → Object/library modules 加入 ws2_32.lib。

2. 介面設計

在對話框上配置以下控制項:

控制項ID類型/變數備註
位址下拉框IDC_COMBOCComboBox m_comb輸入目的 IP/域名
最大跳數編輯框IDC_MAXHOTint m_maxhot限制追蹤跳數
追蹤按鈕IDC_TRACEOnTrace()啟動追蹤
停止按鈕IDC_STOPOnStop()中止追蹤
結果列表IDC_LISTCListCtrl m_list顯示路由節點
程式介面示意圖

圖 3:程式執行介面

3. 核心類別 CICMP 實作

自訂 CICMP 類別封裝 ICMP 封包的建構、發送、接收與解析:

  • Initialize():初始化 Winsock、建立 Raw Socket、設定收發逾時。
  • CheckSum():計算 ICMP 封包檢驗和。
  • SendICMPPack():填充 ICMP 標頭(類型 8、ID 為進程 ID、序號、時間戳),發送封包。
  • RecvICMPPack():接收回應,解析 IP 標頭長度,提取 ICMP 類型判斷是否為 TTL 超時(類型 11)或回應應答(類型 0),並記錄路由器 IP。

核心程式碼片段:

// 設定 TTL
setsockopt(m_Sock, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int));

// 發送 ICMP Echo Request
m_pIcmp->type = ICMP_ECHO;
m_pIcmp->code = 0;
m_pIcmp->ID = (USHORT)GetCurrentProcessId();
m_pIcmp->cksum = CheckSum((USHORT*)m_pIcmp, DEF_PACKET+sizeof(ICMP_HEAD));
sendto(winsock, (char*)m_pIcmp, DEF_PACKET+sizeof(ICMP_HEAD), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));

// 接收並分析回應
recvfrom(winsock, (char*)m_pIp, MAX_PACKET, 0, (sockaddr*)&m_sockAddr, &len);
int ipheadlen = m_pIp->HeadLen * 4;
ICMP_HEAD* p_icmprev = (ICMP_HEAD*)((char*)m_pIp + ipheadlen);
switch(p_icmprev->type) {
    case ICMP_ECHOREPLY:  // 到達目的
    case 11:              // TTL 超時,取得路由器 IP
}

四、執行結果與說明

程式啟動後,在下拉框輸入目的位址(如 www.google.com),設定最大跳數,點擊「追蹤」按鈕,列表框將即時顯示每一跳的路由器 IP、主機名(若可解析)及往返時間。若某跳超時則顯示 *。

程式執行效果圖

圖 4:路由追蹤執行效果

五、總結

本文結合 ICMP 協議原理與 VC++ Socket 程式設計,完整實作了路由追蹤功能。關鍵在於利用 TTL 控制封包壽命,並解析路由器回傳的 ICMP TTL 超時訊息。此技術可應用於網路診斷、拓撲發現等場景。完整原始碼可供下載參考。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved