博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 获取当前设备公网IP
阅读量:5166 次
发布时间:2019-06-13

本文共 4128 字,大约阅读时间需要 13 分钟。

/*!

* \brief 根据域名获取ip
* WIN32
*
* \param char * domain 需要解析的域名
* \return const char * 解析结果
*/
void getDomainIP(const char * domain, char * ip)
{
char ** pptr = NULL;
int i = 0;
char szHostName[256] = {};
struct hostent * pHostEntry = gethostbyname(domain);
if (pHostEntry != NULL)
{
char szIpBuff[32] = {0};
for (i = 1, pptr = pHostEntry->h_addr_list; *pptr != NULL; ++pptr )
{
memset(szIpBuff, 0, sizeof(szIpBuff));
const char* szIpRet = inet_ntop(pHostEntry->h_addrtype, *pptr, szIpBuff, sizeof(szIpBuff));
// inet_ntop的返回值为NULL,则表示失败,否则返回相应的IP地址(此时szIpRet指向的是szIpBuff)
if (szIpBuff != NULL)
{
memcpy(ip, szIpRet, sizeof(char[16]));
}
}
}
}

/*!

* \brief 从http响应中获取ip
*
* \param std::string response
* \return std::string
*/
std::string getIpFromHttpResponse(std::string response)
{
if (!response.empty())
{
// 去掉尾部空白行
response.erase(response.find_last_not_of("\r\n\r\n") + 1);
// 获取最后一行
std::string::size_type pos = response.find_last_of("\r\n\r\n");
bool isGetIp = pos > 0 && pos < response.length();
response = isGetIp ? response.substr(pos, response.length()) : "";
// 判断是否是合法的ip
int tmp1, tmp2, tmp3, tmp4;
int i = sscanf(response.c_str(), "%d.%d.%d.%d", &tmp1, &tmp2, &tmp3, &tmp4);
// 若ip非法则返回空
if (i != 4 || tmp1 > 255 || tmp2 > 255 || tmp3 > 255 || tmp4 > 255)
{
response = "";
}
else
{
char tmp[20];
snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", tmp1, tmp2, tmp3, tmp4);
response = tmp;
HW_WRITE_LOG(log_info, "%s", response.c_str());
}
}
return response;
}

/*!

* \brief 获取IP请求结果
* WIN32
*
* \return std::string 请求相应
*/
std::string httpRequestIp(const char * domain)
{
char ipAddress[16];
memset(ipAddress, 0, sizeof(char[16]));
getDomainIP(domain, ipAddress);
char tmpReq[200];
sprintf(tmpReq, "GET http://%s/ HTTP/1.1\r\nHOST: %s\r\n\r\n", domain, domain);
std::string request = (std::string)tmpReq;
int port = 80;

std::string response;

int resp_leng;
char buffer[1024];
int sock;

#ifdef WIN32

struct sockaddr_in serveraddr;
WSADATA wsaData;

//init winsock

if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
HW_WRITE_LOG(log_error, "WSAStartup() failed");

//open socket

if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
HW_WRITE_LOG(log_error, "socket() failed");

//connect

memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(ipAddress);
serveraddr.sin_port = htons((unsigned short) port);
if (connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
HW_WRITE_LOG(log_error, "connect() failed");

//send request

if (send(sock, request.c_str(), request.length(), 0) != request.length())
HW_WRITE_LOG(log_error, "send() sent a different number of bytes than expected");

#else
int error;
struct sockaddr_in addr;

if((sock = socket(AF_INET,SOCK_STREAM,0))<0)

{
HW_WRITE_LOG(log_error, "Error 01: creating socket failed!");
return "";
}

addr.sin_family = AF_INET;

addr.sin_port = htons(port);
inet_aton(ipAddress,&addr.sin_addr); //this should be the ip of the server I'm contacting

error = connect(sock,(sockaddr*)&addr,sizeof(addr));

if(error!=0)
{
HW_WRITE_LOG(log_error, "Error 02: conecting to server failed!");
return "";
}

send(sock,request.c_str(),request.length(),0);

#endif

//get response

response = "";
resp_leng= 1024;
int revlen = 0;
while (resp_leng == 1024)
{
resp_leng = recv(sock, (char*)&buffer, 1024, 0);
revlen += resp_leng;
if (resp_leng>0)
response+= std::string(buffer).substr(0,resp_leng);
}

std::string answer (response);

#if _WIN32

WSACleanup();
#endif
answer = getIpFromHttpResponse(answer);
return answer;
}
/*!
* \brief 获取本机公网IP
*
* \param char * outBuf 保存结果
* \return void
*/
std::string GetPublicIP() {
//char * domain = "checkip.amazonaws.com";
//std::string answer = httpRequestIp(domain);
// 从多个http域名获取机器使用的外网ip,若获取失败则使用后面的其他域名
std::string domains[3] = {"bot.whatismyipaddress.com", "api.ipify.org", "icanhazip.com"};
std::string answer = "";
int num = sizeof(domains) / sizeof(domains[0]);
for (int i = 0; i <= num - 1; i++)
{
const char * domain = domains[i].c_str();
answer = httpRequestIp(domain);
if (!answer.empty())
{
break;
}
}

return answer;

}

转载于:https://www.cnblogs.com/liujieda/p/10429109.html

你可能感兴趣的文章
Oracle中包的创建
查看>>
关于PHP会话:session和cookie
查看>>
导航,头部,CSS基础
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
面试时被问到的问题
查看>>
注解小结
查看>>
201421410014蒋佳奇
查看>>
Xcode5和ObjC新特性
查看>>
CSS属性值currentColor
查看>>
Real-Time Rendering 笔记
查看>>
多路复用
查看>>
利用SignalR来同步更新Winfrom
查看>>
反射机制
查看>>
CocoaPod
查看>>
BZOJ 1251: 序列终结者 [splay]
查看>>
【UVA】434-Matty&#39;s Blocks
查看>>
hadoop2.2.0+hive-0.10.0完全分布式安装方法
查看>>
使用Reporting Services时遇到的小问题
查看>>
约瑟夫问题
查看>>