C/C++ 利用IP地址得到物理位置
扫描二维码
随时随地手机看文章
利用IP地址得到物理位置:
原理:这里要讲的就是通过socket去发送GET请求,发送至转换的网站,然后解析其中的内容,这里GET的是http://ip.chinaz.com/网站。
步骤:
先使用Wireshark抓包工具,抓取查询http://ip.chinaz.com/的封包,然后就可以模仿这个封包,利用socket发送GET请求,获取IP地址的物理地址信息了。
从上面可以得到要发送的封包的具体格式:
GET /?IP=223.124.1.232 HTTP/1.1rn Host: ip.chinaz.comrn Connection: keep-alivern Upgrade-Insecure-Requests: 1rn User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36rn Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8rn Accept-Language: zh-CN,zh;q=0.8rnrn
使用socket进行send发送时,缓冲区填入上面的固定格式即可,这里要改的只有?IP=你要查询的IP地址
这里还要强调一点,在上面的封包中最好不要加上Accept-Encoding: gzip, deflate, sdchrn,除非你会使用代码解压gzip压缩包,否则recv接收服务器响应回来的文档的时候,发送的是gzip压缩过的数据。由于我们只是查询而已,所以去掉这个字段,让服务器直接发回来html文档,然后我们解析就可以了。
下面是一个解析http://ip.chinaz.com/获取物理地址的例子:
//名字转IP(OK,New) char* NET::GetIp(char* szhostname) { char* szip = NULL; char* ipbit = NULL; hostent* ipstr = NULL; szip = new char[30]; if (!szip) goto Err; ZeroMemory(szip, 30); ipstr = gethostbyname(szhostname); if (ipstr == NULL) goto Err; ipbit = inet_ntoa(*(in_addr*)ipstr->h_addr); if (ipbit == NULL) goto Err; memcpy(szip, ipbit, strlen(ipbit)); return szip; Err: return NULL; } //连接HTTP服务器(OK,Connected) SOCKET NET::ConnectHttpServer(char* szip) { SOCKET szclient_socket = 0; szclient_socket = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == szclient_socket) goto Err; //连接服务器 SOCKADDR_IN info; info.sin_port = htons(80); info.sin_family = AF_INET; info.sin_addr.S_un.S_addr = inet_addr(szip); if (0 != connect(szclient_socket, (SOCKADDR*)&info, sizeof(SOCKADDR))) goto Err; //返回 return szclient_socket; Err: if (szclient_socket != NULL && szclient_socket != INVALID_SOCKET) { closesocket(szclient_socket); szclient_socket = 0; } return 0; } //设置套接字缓冲区大小(OK) BOOL NET::SetSocketInfo(SOCKET szsocket,int uBufferSize) { if (SOCKET_ERROR == setsockopt(szsocket, SOL_SOCKET, SO_RCVBUF, (char*)&uBufferSize, sizeof(int))) goto Err; if (SOCKET_ERROR == setsockopt(szsocket, SOL_SOCKET, SO_SNDBUF, (char*)&uBufferSize, sizeof(int))) goto Err; return TRUE; Err: return FALSE; } //UTF8转ANSI字符串(OK,New) char* STR::Utf8ToAnsi(char* utf8,int len,char szcc) { BOOL szok = FALSE; int szlen = 0; char* szretstr = NULL; wchar_t* whar_str = NULL; //UTF8转UNICODE szlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0); if (szlen <= 0) goto Err; szlen += 1; whar_str = new wchar_t[szlen]; if (!whar_str) goto Err; ZeroMemory(whar_str, szlen * sizeof(wchar_t)); MultiByteToWideChar(CP_UTF8, 0, utf8, len, whar_str, szlen); if (GetLastError() != 0) goto Err; //UNICODE转ANSI szlen = WideCharToMultiByte(CP_ACP, 0, whar_str, len, NULL, 0,&szcc,&szok); if (szlen <= 0) goto Err; szlen += 1; szretstr = new char[szlen]; if (!szretstr) goto Err; ZeroMemory(szretstr, szlen * sizeof(char)); WideCharToMultiByte(CP_ACP, 0, whar_str, len, szretstr, szlen, &szcc, &szok); if (GetLastError() != 0) goto Err; if (whar_str) { delete[] whar_str; whar_str = NULL; } return szretstr; Err: if (whar_str) { delete[]whar_str; whar_str = NULL; } return NULL; } //获取物理地址(OK,ip.chinaz.com,New) char* GET_POINT::GetPoint(char* ip_address,char* get_ip_de_host_name) { int szlen = 0; char* szPoint = NULL; char* szTemp = NULL; char* szTemp2 = NULL; char* szTemp3 = NULL; char* get_host_name_ip = NULL; SOCKET http_client_socket = NULL; char packet[400] ="GET /"; strcat(packet, "?IP="); strcat(packet, ip_address); strcat(packet, " HTTP/1.1rn" "Host: " ); strcat(packet, get_ip_de_host_name); strcat(packet, "rn" "Connection: keep-alivern" "Cache-Control: max-age=0rn" "Upgrade-Insecure-Requests: 1rn" "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8rn" "Accept-Language: zh-CN,zh;q=0.8rnrn" ); char* recv_buffer = NULL; //代码开始 recv_buffer = new char[50000]; if (!recv_buffer) goto Err; ZeroMemory(recv_buffer, 50000); //返回解析物理地址的主机的IP地址 get_host_name_ip = NET::GetIp(get_ip_de_host_name); if (get_host_name_ip == NULL) goto Err; //连接服务器 http_client_socket = NET::ConnectHttpServer(get_host_name_ip); if (http_client_socket == 0) goto Err; //设置缓冲区大小 if (!NET::SetSocketInfo(http_client_socket, 30000)) goto Err; if (send(http_client_socket, packet, strlen(packet), 0) <= 0) goto Err; if (recv(http_client_socket, recv_buffer, 50000, 0) "); //??? if (szTemp == NULL) goto Err; szTemp2 = strchr(szTemp, '<'); if (szTemp2 == NULL) goto Err; szlen = szTemp2 - szTemp; if (szlen <= 0) goto Err; szlen += 1; szPoint = new char[szlen]; if (!szPoint) goto Err; ZeroMemory(szPoint, szlen); memcpy(szPoint, szTemp, szlen - 1); if (get_host_name_ip) { delete[]get_host_name_ip; get_host_name_ip = NULL; } if (http_client_socket) { closesocket(http_client_socket); http_client_socket = 0; } if (recv_buffer) { delete[]recv_buffer; recv_buffer = NULL; } if (szTemp3) { delete[]szTemp3; szTemp3 = NULL; } return szPoint; Err: if (get_host_name_ip) { delete[]get_host_name_ip; get_host_name_ip = NULL; } if (http_client_socket) { closesocket(http_client_socket); http_client_socket = 0; } if (recv_buffer) { delete[]recv_buffer; recv_buffer = NULL; } if (szTemp3) { delete[]szTemp3; szTemp3 = NULL; } return NULL; }
实现: