原始通訊端透析之實現Ping)

來源:互聯網
上載者:User
極其常用的Ping命令通過向電腦發送ICMP Echo請求報文並且監聽回應報文的返回,以校正與遠端電腦或本機電腦的串連。

  使用ICMP.DLL實現Ping

  在Windows平台編程中實現Ping的一個最簡單方法是調用ICMP.DLL這個動態連結程式庫,引用ICMP.DLL中的三個函數即可:

HANDLE IcmpCreateFile(void);

  這個函數開啟個ICMP Echo請求能使用的控制代碼;

BOOL IcmpCloseHandle(HANDLE IcmpHandle);

  這個函數關閉由IcmpCreateFile開啟的控制代碼;

DWORD IcmpSendEcho(
 HANDLE IcmpHandle, // IcmpCreateFile開啟的控制代碼
 IPAddr DestinationAddress, //Echo請求的目的地址
 LPVOID RequestData, //發送資料buffer
 WORD RequestSize, //發送資料長度
 PIP_OPTION_INFORMATION RequestOptions, // IP_OPTION_INFORMATION指標
 LPVOID ReplyBuffer, //接收回複buffer
 DWORD ReplySize, //接收回複buffer大小
 DWORD Timeout //等待逾時
);

  這個函數發送Echo請求並等待回複或逾時。

  把這個函數和相關資料封裝成一個類CPing,CPing類的標頭檔如下:

class CPing
{
 public:
  CPing();
  ~CPing();
  BOOL Ping(char* strHost);
 private:
  // ICMP.DLL 匯出函數指標
  HANDLE (WINAPI *pIcmpCreateFile)(VOID);
  BOOL (WINAPI *pIcmpCloseHandle)(HANDLE);
  DWORD (WINAPI *pIcmpSendEcho)(HANDLE,DWORD,LPVOID,WORD,PIPINFO,LPVOID,DWORD,DWORD);
  HANDLE hndlIcmp; // 載入ICMP.DLL庫控制代碼
  BOOL bValid; //是否構造(獲得ICMP.DLL匯出函數指標和初始化WinSock)成功
};

  CPing類的建構函式獲得ICMP.DLL中匯出函數的指標並初始化WinSock:

CPing::CPing()
{
 bValid = FALSE;
 WSADATA wsaData;
 int nRet;
 // 動態載入ICMP.DLL
 hndlIcmp = LoadLibrary("ICMP.DLL");
 if (hndlIcmp == NULL)
 {
  ::MessageBox(NULL, "Could not load ICMP.DLL", "Error:", MB_OK);
  return;
 }
 // 獲得ICMP.DLL中匯出函數指標
 pIcmpCreateFile = (HANDLE (WINAPI *)(void))GetProcAddress((HMODULE)hndlIcmp,"IcmpCreateFile");
 pIcmpCloseHandle = (BOOL (WINAPI *)(HANDLE))GetProcAddress((HMODULE)hndlIcmp,"IcmpCloseHandle");
 pIcmpSendEcho = (DWORD (WINAPI *)(HANDLE,DWORD,LPVOID,WORD,PIPINFO,LPVOID,DWORD,DWORD))
GetProcAddress((HMODULE)hndlIcmp,"IcmpSendEcho");
 // 檢查所有的指標
 if (pIcmpCreateFile == NULL || pIcmpCloseHandle == NULL ||pIcmpSendEcho == NULL)
 {
  ::MessageBox(NULL, "Error loading ICMP.DLL", "Error:", MB_OK);
  FreeLibrary((HMODULE)hndlIcmp);
  return;
 }

 // 初始化WinSock
 nRet = WSAStartup(0x0101, &wsaData );
 if (nRet)
 {
  ::MessageBox(NULL, "WSAStartup() error:", "Error:", MB_OK);
  WSACleanup();
  FreeLibrary((HMODULE)hndlIcmp);
  return;
 }
 // 檢查WinSock的版本
 if (0x0101 != wsaData.wVersion)
 {
  ::MessageBox(NULL, "No WinSock version 1.1 support found", "Error:", MB_OK);
  WSACleanup();
  FreeLibrary((HMODULE)hndlIcmp);
  return;
 }
 bValid = TRUE;
}

  CPing類的解構函式完成相反的動作:

CPing::~CPing()
{
 WSACleanup();
 FreeLibrary((HMODULE)hndlIcmp);
}

  CPing類的Ping函數是最核心的函數,實現真正的ping操作:

int CPing::Ping(char *strHost)
{
 struct in_addr iaDest; // Internet地址結構體
 LPHOSTENT pHost; // 主機入口結構體指標
 DWORD *dwAddress; // IP地址
 IPINFO ipInfo; // IP選項結構體
 ICMPECHO icmpEcho; // ICMP Echo回複buffer
 HANDLE hndlFile; // IcmpCreateFile函數開啟的控制代碼

 if (!bValid)
 {
  return FALSE;
 }

 //使用inet_addr()以判定ping目標為地址還是名稱
 iaDest.s_addr = inet_addr(strHost);
 if (iaDest.s_addr == INADDR_NONE)
  pHost = gethostbyname(strHost);
 else
  pHost = gethostbyaddr((const char*) &iaDest, sizeof(struct in_addr),AF_INET);
  if (pHost == NULL)
  {
   return FALSE;
  }

  // 拷貝IP地址
  dwAddress = (DWORD*)(*pHost->h_addr_list);

  // 獲得ICMP Echo控制代碼
  hndlFile = pIcmpCreateFile();

  // 設定發送資訊預設值
  ipInfo.Ttl = 255;
  ipInfo.Tos = 0;
  ipInfo.IPFlags = 0;
  ipInfo.OptSize = 0;
  ipInfo.Options = NULL;
  icmpEcho.Status = 0;
  // 請求一個ICMP echo
  pIcmpSendEcho(hndlFile, *dwAddress, NULL, 0, &ipInfo, &icmpEcho, sizeof(struct tagICMPECHO), 1000);

  //設定結果
  iaDest.s_addr = icmpEcho.Source;
  if (icmpEcho.Status)
  {
   return FALSE;
  }

  // 關閉ICMP Echo控制代碼
  pIcmpCloseHandle(hndlFile);
  return TRUE;
}

  其中所使用的相關結構體定義為:

typedef struct tagIPINFO
{
 u_char Ttl; // TTL
 u_char Tos; // 服務類型
 u_char IPFlags; // IP標誌
 u_char OptSize; // 可選資料大小
 u_char *Options; // 可選資料buffer
} IPINFO, *PIPINFO;

typedef struct tagICMPECHO
{
 u_long Source; // 源地址
 u_long Status; // IP狀態
 u_long RTTime; // RTT
 u_short DataSize; // 回複資料大小
 u_short Reserved; // 保留
 void *pData; // 回複資料buffer
 IPINFO ipInfo; // 回複IP選項
} ICMPECHO, *PICMPECHO;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.