在網絡編程中,獲取本機的公網IP地址是一個常見需求。本文介紹如何使用C語言配合Windows網絡API,通過訪問外部服務來獲取公網IP地址。
由於本機通常位於NAT或路由器後方,無法直接從網卡獲取公網IP。解決方案是向提供IP查詢服務的網站發送HTTP請求,解析返回的HTML頁面提取IP地址。本示例使用ip138.com作為查詢服務。
[cpp]
#include "stdafx.h"
BOOL GetPubIp(char *ip);
int main()
{
char myip[32]={0};
GetPubIp(myip);
cout<<myip<<endl;
return 0;
}
BOOL GetPubIp(char *ip)
{
HINTERNET hInternet=NULL;
HINTERNET hConnect=NULL;
char szText[512]={0};
char *szAccept="Accept: */*\r\n\r\n";
char *szUrl="https://www.ip138.com/ip2city.asp";
DWORD dwReadLen=0;
__try
{
hInternet=InternetOpen("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",0,NULL,NULL,0);
if(!hInternet)
__leave;
hConnect=InternetOpenUrl(hInternet,szUrl,szAccept,strlen(szAccept),INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_RELOAD,0);
if(!hConnect)
__leave;
InternetReadFile(hConnect,szText,512,&dwReadLen);
}
__finally
{
if(hInternet)
InternetCloseHandle(hInternet);
if(hConnect)
InternetCloseHandle(hConnect);
}
char *start=strstr(szText,"您的IP地址是:[");
if(!start)
return FALSE;
start=start+15;
char *temp=strstr(start,"]");
strncpy(ip,start,temp-start);
return TRUE;
}
代碼使用了Windows提供的WinINet API(InternetOpen、InternetOpenUrl、InternetReadFile、InternetCloseHandle)進行HTTP通信。這組API封裝了Socket層細節,適合簡單的HTTP客戶端開發。
使用__try/__finally結構確保網絡句柄在任何情況下都能正確關閉,防止資源洩漏。這在網絡編程中尤為重要,因為連接失敗、超時等異常情況頻繁發生。
通過strstr查找特定標記「您的IP地址是:[」和「]」,提取中間的IP字符串。這種基於特徵字符串的解析方式簡單直接,但依賴目標網站頁面結構穩定。
Linux/Unix系統下可使用libcurl庫實現相同功能,代碼更簡潔且支持HTTPS、超時控制、重定向等高級特性。C++17以降可考慮使用std::experimental::net或第三方網絡庫(如Boost.Beast、cpp-httplib)。
本示例展示了Windows平台下最基礎的HTTP GET請求與響應解析流程,適合理解網絡編程基本原理,生產環境建議使用更健壯的網絡庫。