如何在 C++ 中查找用户的外部 IP?我需要一种适用于任何系统的方法,而不仅仅是我的系统。此外,系统可能位于路由器后面,因此 NAT 将发挥作用,从而使检索外部 IP 变得更加困难。
理想情况下,我希望不使用任何第三方服务(例如whatsmyip)来执行此操作。但是,我不确定这是否可能。如果我不使用第 3 方服务,我必须通过路由器,如果 ping 被禁用,我猜这可能是不可能的(我可能是错的,不太确定)。
如果我要使用像whatsmyip 这样的第三方服务,我该怎么办?他们是否公开了 Web 服务?我看过这个链接:http://automation.whatismyip.com/n09230945.asp但它似乎不起作用。 是否可以使用某些 HTTP 方法获取外部 IP 并检索它,或者我是否需要有效地抓取页面以从中获取 IP?
我仅限于使用 Windows API 来完成此操作(无第 3 方 API)
理论上,您可以使用 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 地址。
这里是winsock方式。它只是提取服务器发送的 HTML 代码中嵌入的 IP 地址。
此代码使用http://api.ipify.org/
.
下面是两个不同的代码。一种适用于 VS2012-2015,使用 strcpy_s( )
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++ 或任何语言无关。
#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;
}
}