C++ 获取当前设备公网IP
/*!* \brief 根据域名获取ip
* WIN32
*
* \param char * domain 需要解析的域名
* \return const char * 解析结果
*/
void getDomainIP(const char * domain, char * ip)
{
char ** pptr = NULL;
int i = 0;
char szHostName = {};
struct hostent * pHostEntry = gethostbyname(domain);
if (pHostEntry != NULL)
{
char szIpBuff = {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));
}
}
}
}
/*!
* \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;
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;
memset(ipAddress, 0, sizeof(char));
getDomainIP(domain, ipAddress);
char tmpReq;
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;
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 = {"bot.whatismyipaddress.com", "api.ipify.org", "icanhazip.com"};
std::string answer = "";
int num = sizeof(domains) / sizeof(domains);
for (int i = 0; i <= num - 1; i++)
{
const char * domain = domains.c采用str();
answer = httpRequestIp(domain);
if (!answer.empty())
{
break;
}
}
return answer;
页:
[1]