如何在C++中获取外部IP地址?

问题描述 投票:0回答:5

如何在 C++ 中查找用户的外部 IP?我需要一种适用于任何系统的方法,而不仅仅是我的系统。此外,系统可能位于路由器后面,因此 NAT 将发挥作用,从而使检索外部 IP 变得更加困难。

理想情况下,我希望不使用任何第三方服务(例如whatsmyip)来执行此操作。但是,我不确定这是否可能。如果我不使用第 3 方服务,我必须通过路由器,如果 ping 被禁用,我猜这可能是不可能的(我可能是错的,不太确定)。

如果我要使用像whatsmyip 这样的第三方服务,我该怎么办?他们是否公开了 Web 服务?我看过这个链接:http://automation.whatismyip.com/n09230945.asp但它似乎不起作用。 是否可以使用某些 HTTP 方法获取外部 IP 并检索它,或者我是否需要有效地抓取页面以从中获取 IP?

我仅限于使用 Windows API 来完成此操作(无第 3 方 API)

c++ http ip-address
5个回答
4
投票

理论上,您可以使用 Windows uPnP API 来执行此操作。您首先使用

UPnPDeviceFinder
枚举 Internet 网关设备。然后你得到一个网关的
IUPnPRemoteEndpointInfo
(嗯,通常只有一个)并调用它的GetStringValue,传递一个包含
"RemoteAddress"
的字符串来获取它的远程地址(我认为
意味着它的外部地址)地址,尽管我承认我并不完全确定)。哦,因为这是 COM,所以它必须是系统字符串,而不是普通字符串。
从外部提供商获取 IP 更容易

。在不使用任何 3

rd 方库的情况下,其代码如下所示: #include <windows.h> #include <wininet.h> #include <string> #include <iostream> std::string real_ip() { HINTERNET net = InternetOpen("IP retriever", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); HINTERNET conn = InternetOpenUrl(net, "http://myexternalip.com/raw", NULL, 0, INTERNET_FLAG_RELOAD, 0); char buffer[4096]; DWORD read; InternetReadFile(conn, buffer, sizeof(buffer)/sizeof(buffer[0]), &read); InternetCloseHandle(net); return std::string(buffer, read); } int main() { std::cout << real_ip() << "\n"; }

编译为:

cl ip_addr.cpp wininet.lib

注意:如果您的计算机配置为使用 IPv6,这可以(并且将会)检索您的 IPv6 地址。
    


2
投票

这里是winsock方式。它只是提取服务器发送的 HTML 代码中嵌入的 IP 地址。

此代码使用

http://api.ipify.org/

.

下面是两个不同的代码。一种适用于 VS2012-2015,使用 strcpy_s( )

,另一种适用于 Visual C++ 6.0,使用

strcpy( )

,因为 VS2012-2015 会抛出一条错误消息,提示您使用 
strcpy_s( )
 而不是 
strcpy( )
Visual Studio 2012-2015 代码。

#include "stdafx.h" #include <string.h> #include <winsock2.h> #include <windows.h> #include <iostream> #include <vector> #include <locale> #include <sstream> using namespace std; #pragma comment(lib,"ws2_32.lib") string website_HTML; locale local; void get_Website(string url); char lineBuffer[200][80] = { ' ' }; char buffer[10000]; char ip_address[16]; int i = 0, bufLen = 0, j = 0, lineCount = 0; int lineIndex = 0, posIndex = 0; //**************************************************** int main(void){ cout << "\n\n\n"; get_Website("api.ipify.org"); for (size_t i = 0; i<website_HTML.length(); ++i) website_HTML[i] = tolower(website_HTML[i], local); istringstream ss(website_HTML); string stoken; while (getline(ss, stoken, '\n')) { //cout <<"-->"<< stoken.c_str() << '\n'; strcpy_s(lineBuffer[lineIndex], stoken.c_str()); int dot = 0; for (int ii = 0; ii< strlen(lineBuffer[lineIndex]); ii++){ if (lineBuffer[lineIndex][ii] == '.') dot++; if (dot >= 3){ dot = 0; strcpy_s(ip_address, lineBuffer[lineIndex]); } } lineIndex++; } cout << "Your IP Address is " << ip_address << " \n\n"; cout << "\nPress ANY key to close.\n\n"; cin.ignore(); cin.get(); return 0; } //**************************************************** void get_Website(string url){ WSADATA wsaData; SOCKET Socket; SOCKADDR_IN SockAddr; int lineCount = 0; int rowCount = 0; struct hostent *host; string get_http; get_http = "GET / HTTP/1.1\r\nHost: " + url + "\r\nConnection: close\r\n\r\n"; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ cout << "WSAStartup failed.\n"; system("pause"); //return 1; } Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); host = gethostbyname(url.c_str()); SockAddr.sin_port = htons(80); SockAddr.sin_family = AF_INET; SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr); if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){ cout << "Could not connect"; system("pause"); //return 1; } send(Socket, get_http.c_str(), strlen(get_http.c_str()), 0); int nDataLength; while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){ int i = 0; while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){ website_HTML += buffer[i]; i += 1; } } closesocket(Socket); WSACleanup(); }

Visual C++ 6.0 代码

#include <string.h> #include <winsock2.h> #include <windows.h> #include <iostream> #include <vector> #include <locale> #include <sstream> using namespace std; #pragma comment(lib,"ws2_32.lib") string website_HTML; locale local; void get_Website(string url ); char lineBuffer[200][80] ={' '}; char buffer[10000]; char ip_address[16]; int i = 0, bufLen=0, j=0,lineCount=0; int lineIndex=0, posIndex=0; //**************************************************** int main( void ){ cout << "\n\n\n"; get_Website("api.ipify.org" ); for (size_t i=0; i<website_HTML.length(); ++i) website_HTML[i]= tolower(website_HTML[i],local); istringstream ss(website_HTML); string stoken; while(getline(ss, stoken, '\n')) { strcpy(lineBuffer[lineIndex],stoken.c_str()); int dot=0; for (int ii=0; ii< strlen( lineBuffer[lineIndex] ); ii++ ){ if (lineBuffer[lineIndex][ii] == '.') dot++; if (dot>=3){ dot=0; strcpy(ip_address,lineBuffer[lineIndex]); } } lineIndex++; } cout<<"Your IP Address is "<< ip_address<<" \n\n"; cout<<"\nPress ANY key to close.\n\n"; cin.ignore(); cin.get(); return 0; } //**************************************************** void get_Website(string url ){ WSADATA wsaData; SOCKET Socket; SOCKADDR_IN SockAddr; int lineCount=0; int rowCount=0; struct hostent *host; string get_http; get_http = "GET / HTTP/1.1\r\nHost: " + url + "\r\nConnection: close\r\n\r\n"; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){ cout << "WSAStartup failed.\n"; system("pause"); //return 1; } Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); host = gethostbyname(url.c_str()); SockAddr.sin_port=htons(80); SockAddr.sin_family=AF_INET; SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr); if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){ cout << "Could not connect"; system("pause"); //return 1; } send(Socket,get_http.c_str(), strlen(get_http.c_str()),0 ); int nDataLength; while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){ int i = 0; while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){ website_HTML+=buffer[i]; i += 1; } } closesocket(Socket); WSACleanup(); }

这与 C++ 或任何语言无关。

1
投票
您必须使用外部实体 - 通常是某种网络服务,它将报告与其联系的路由器的 IP 地址。

这是某人的
示例问题
问如何在 PHP 中获取客户端 IP 地址。

您可以使用像curl或curlpp这样的库来获取

0
投票
的内容。它的响应只是你的外部ip,你可以读取和使用它。

Jerry Coffin 版本的 ANSI C 版本,为那些寻找此问题的 C 解决方案的人提供了额外的检查。

0
投票
#define EXTERNAL_IP_RESOLVER "http://api.ipify.org/" #define BUFFER_SIZE 256 char* real_ip() { HINTERNET net = InternetOpenA("IP retriever", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (!net) { return NULL; } HINTERNET conn = InternetOpenUrlA(net, EXTERNAL_IP_RESOLVER, NULL, 0, INTERNET_FLAG_RELOAD, 0); if (!conn) { InternetCloseHandle(net); return NULL; } char buffer[BUFFER_SIZE]; DWORD read; if (InternetReadFile(conn, buffer, sizeof(buffer) - 1, &read)) { buffer[read] = '\0'; } else { InternetCloseHandle(conn); InternetCloseHandle(net); return NULL; } InternetCloseHandle(conn); InternetCloseHandle(net); char* result = (char*)malloc(read + 1); if (result) { strcpy(result, buffer); return result; } else { return NULL; } }


© www.soinside.com 2019 - 2024. All rights reserved.