[Help]获取公网IP问题?

cfans_2011 2010-12-14 04:45:40
下面的代码用来获取公网IP,一般用户可以获取到。
但是通过代理上网的用户获取不到,提示网络缓存拒绝访问。

主要通过两种方式来实现:
一个是向WEB服务器模拟发包,解析返回的数据包;
另外一个方式是获取WEB页面的源代码,解析其中的IP地址。

访问的WEB页面是:
http://www.ip138.com/ip2city.asp


// GetPubIPDlg.cpp : implementation file

#pragma comment(lib,"ws2_32.lib")
#include <afxinet.h> //加入CIneternetSession的引用

//写文本文件
BOOL wFile(CString filePath,CString fileContent)
{
CFile file;
file.Open(filePath,CFile::modeCreate|CFile::modeWrite);
file.Write(fileContent,fileContent.GetLength());
file.Close();
return TRUE;
}

//测试模拟发包
void CGetPubIPDlg::testSendData(char *sData,CString strFilePath)
{
SOCKADDR_IN saServer;
LPHOSTENT lphostent;
WSADATA wsadata;
SOCKET hsocket;

int nRet;
char* host_name="www.ip138.com";
CString strBottomLine;
CString strReplyContet;

//要写入文本文件的内容
CString logContent;

// 初始化套接字
if(WSAStartup(MAKEWORD(2,2),&wsadata))
{
AfxMessageBox("初始化SOCKET出错");
return;
}

lphostent=gethostbyname(host_name);
if(lphostent==NULL)
{
AfxMessageBox("本地电脑没有IP");
return;
}

hsocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
saServer.sin_family = AF_INET;
saServer.sin_port = htons(80); //默认端口
saServer.sin_addr = *((LPIN_ADDR)*lphostent->h_addr_list); //***本地IP地址***

// 利用SOCKET连接
nRet = connect(hsocket,(LPSOCKADDR)&saServer,sizeof(SOCKADDR_IN));
if(nRet == SOCKET_ERROR)
{
AfxMessageBox("建立连接时出错");
closesocket(hsocket);
return ;
}

//发送的数据包写文本文件
logContent.Insert(logContent.GetLength(),"发送的数据包:\r\n");
logContent.Insert(logContent.GetLength(),sData);
wFile(strFilePath,logContent);

//利用SOCKET发送 ******
nRet = send(hsocket,sData,strlen(sData),0);

if(nRet==SOCKET_ERROR)
{
AfxMessageBox("发送数据包时出错");
closesocket(hsocket);
}

Sleep(100);

char Dest[3000];
nRet=1;
CString strMsg;
// 接收返回数据包
nRet=recv(hsocket,(LPSTR)Dest,sizeof(Dest),0);
Dest[nRet] =0;

CString strPubIP; //公网IP地址
strMsg.Format("%s",Dest);

//收到的Socket数据包写文本文件
logContent.Insert(logContent.GetLength(),"收到的Socket数据包:\r\n");
logContent.Insert(logContent.GetLength(),strMsg);
wFile(strFilePath,logContent);

CString strIPHead = ":[";
CString strIPTail ="] ";

//解析公网IP地址
strMsg = strMsg.Right(strMsg.GetLength()-strMsg.Find(strIPHead)-3);
strPubIP = strMsg.Left(strMsg.GetLength()-strMsg.Find(strIPTail)-14);

strPubIP = "公网IP: "+strPubIP;
AfxMessageBox(strPubIP);
}

//方法一
void CGetPubIPDlg::OnButton1()
{
//请求的数据包
char* req1= "GET /ip2city.asp HTTP/1.1\r\n"
"Accept: */*\r\n"
"Accept-Language: zh-cn\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\n"
"Host: www.ip138.com\r\n"
"Connection: Keep-Alive\r\n\r\n";

testSendData(req1,"收发的数据包-01.txt");
}

//方法二
void CGetPubIPDlg::OnButton2()
{
//请求的数据包
char* req2= "GET /ip2city.asp HTTP/1.1\r\n"
"Accept: */*\r\n"
"Accept-Language: zh-cn\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\n"
"Host: www.ip138.com\r\n"
"Connection: Close\r\n\r\n";

testSendData(req2,"收发的数据包-02.txt");
}

//方法三
void CGetPubIPDlg::OnButton3()
{
//请求的数据包
char* req3= "GET /ip2city.asp HTTP/1.1\r\n"
"Accept: */*\r\n"
"Accept-Language: zh-cn\r\n"
//"Accept-Encoding: gzip, deflate\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\n"
"Host: www.ip138.com\r\n"
"Connection: Keep-Alive\r\n\r\n";

testSendData(req3,"收发的数据包-03.txt");
}

//方法四
void CGetPubIPDlg::OnButton4()
{
//请求的数据包
char* req4= "GET /ip2city.asp HTTP/1.1\r\n"
"Accept: */*\r\n"
"Accept-Language: zh-cn\r\n"
//"Accept-Encoding: gzip, deflate\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\n"
"Host: www.ip138.com\r\n"
"Connection: Close\r\n\r\n";

testSendData(req4,"收发的数据包-04.txt");
}

//方法五 获取远程页面的源文件
void CGetPubIPDlg::OnButton5()
{
CString m_SiteName ="http://www.ip138.com/ip2city.asp";
CString m_SiteInfo ="";
CInternetSession mySession(NULL,0);
CHttpFile* myHttpFile=NULL;

m_SiteInfo="连接到站点"+m_SiteName+"\r\n";
UpdateData(false);

CString myData;
myHttpFile=(CHttpFile*)mySession.OpenURL(m_SiteName);

while(myHttpFile->ReadString(myData))
{
m_SiteInfo=m_SiteInfo+"\r\n";
m_SiteInfo+=myData;
}

myHttpFile->Close ;
mySession.Close ;

//远程文件的源代码写文本文件
wFile("远程页面源文件.txt",m_SiteInfo);

//从源代码中解析出公网IP地址
CString strIPHead = ":[";
CString strIPTail ="] ";

//截取公网IP地址
CString strPubIP;
m_SiteInfo = m_SiteInfo.Right(m_SiteInfo.GetLength()-m_SiteInfo.Find(strIPHead)-3);
strPubIP = m_SiteInfo.Left(m_SiteInfo.GetLength()-m_SiteInfo.Find(strIPTail)-14);

//拼接公网IP和内网IP
strPubIP = "您的公网IP是:\r\n"+strPubIP;
AfxMessageBox(strPubIP);
}
...全文
226 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wang471981125 2011-02-16
  • 打赏
  • 举报
回复
subyg_0009 2010-12-15
  • 打赏
  • 举报
回复
模拟发包:
GET /ip2city.asp HTTP/1.1
Host: www.ip138.com
Connection:Close
cfans_2011 2010-12-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hzy694358 的回复:]
引用 2 楼 visualeleven 的回复:

tracert www.xxx.com 命令中就有你的公网IP地址

发现该命令和http://www.ip138.com/ip2city.asp 网得到的IP不一致,
哪个才是正确的呢……
[/Quote]
-----------------
这个命令用来获取经过的所有路由IP地址吧?
hzy694358 2010-12-15
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]

tracert www.xxx.com 命令中就有你的公网IP地址
[/Quote]
发现该命令和http://www.ip138.com/ip2city.asp 网得到的IP不一致,
哪个才是正确的呢……
HacKer_27849587 2010-12-15
  • 打赏
  • 举报
回复
4050
cfans_2011 2010-12-15
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]
tracert www.xxx.com 命令中就有你的公网IP地址
[/Quote]
-----------------
tracert www.ip138.com
代理方式上网,代理服务器的IP也获取不到。。。
LuciferStar 2010-12-15
  • 打赏
  • 举报
回复
收藏![Quote=引用 6 楼 tanwei1002 的回复:]
附上SOCKET5代理访问的代码,楼主可以参考,这代码是我某程序通过代理登录中所用



C/C++ code
typedef struct
{
BYTE Ver;
BYTE nMethods;
BYTE Methods[2];
}REQ1_SOCK5,*LPREQ1_SOCK5;
typedef struct
{
BYTE Ver……
[/Quote]
cfans_2011 2010-12-14
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 tanwei1002 的回复:]
附上SOCKET5代理访问的代码,楼主可以参考,这代码是我某程序通过代理登录中所用



C/C++ code
typedef struct
{
BYTE Ver;
BYTE nMethods;
BYTE Methods[2];
}REQ1_SOCK5,*LPREQ1_SOCK5;
typedef struct
{
BYTE Ver……
[/Quote]
---------------------
十分感谢,我试下看看。。。
cfans_2011 2010-12-14
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]
tracert www.xxx.com 命令中就有你的公网IP地址
[/Quote]
-------------------
代理上网也能用这个来获取IP么?

tracert www.ip138.com
tanwei1002 2010-12-14
  • 打赏
  • 举报
回复
附上SOCKET5代理访问的代码,楼主可以参考,这代码是我某程序通过代理登录中所用


typedef struct  
{
BYTE Ver;
BYTE nMethods;
BYTE Methods[2];
}REQ1_SOCK5,*LPREQ1_SOCK5;
typedef struct
{
BYTE Ver;
BYTE Method;
}ANS1_SOCK5,*LPANS1_SOCK5;


typedef struct
{
BYTE Ver;
BYTE Status;
}ANS_AUTHEN_SOCK5,*LPANS_AUTHEN_SOCK5;

typedef struct
{
BYTE Ver;
BYTE Cmd;
BYTE Rsv;
BYTE Atyp;
BYTE other;
}REQ2_SOCK5,*LPREQ2_SOCK5;
typedef struct
{
BYTE Ver;
BYTE Rep;
BYTE nMethods;
BYTE Methods[2];
}ANS2_SOCK5,*LPANS2_SOCK5;

//通过Socks5代理连接服务器
int ConnectServerBySocks5Proxy(
LPCTSTR lpszServerAddr,
DWORD nServerPort,
LPCTSTR lpszProxyAddr,
DWORD nProxyPort,
LPCTSTR lpszProxyAccount,
LPCTSTR lpszProxyPwd
)
{
char buf[1024+1]={0};
int iProxyAccountLen,iProxyPwdLen;
int cbRecv = 0;
int cbSend = 0;
struct hostent* he = NULL;
struct sockaddr_in svrAddr;
SOCKET sock = 0;

LPREQ1_SOCK5 m_proxyreq1;
LPREQ2_SOCK5 m_proxyreq2;
LPANS1_SOCK5 m_proxyans1;
LPANS2_SOCK5 m_proxyans2;
LPANS_AUTHEN_SOCK5 m_authans;


if( !lpszServerAddr || !lpszProxyAddr || !lpszProxyAccount || !lpszProxyPwd ){
return -1;
}

iProxyAccountLen = strlen( lpszProxyAccount );
iProxyPwdLen = strlen( lpszProxyPwd );



//参数检查
if ( iProxyAccountLen > 255 || iProxyPwdLen > 255 )
return -2;//非法的帐号或密码


if ((he=gethostbyname(lpszProxyAddr)) == NULL) { // get the host info
return -3;//获取远程主机信息失败,原因:IP解析失败或无效的IP,或网络不通
}
svrAddr.sin_family = AF_INET; // host byte order
svrAddr.sin_port = htons( (u_short)nProxyPort ); // short, network byte order
svrAddr.sin_addr = *((struct in_addr *)he->h_addr);
ZeroMemory( svrAddr.sin_zero, sizeof(svrAddr.sin_zero) ); // zero the rest of the struct

sock = socket(AF_INET, SOCK_STREAM, 0);
if( INVALID_SOCKET == sock ){
return -4;
}


if ( SOCKET_ERROR == connect(sock,(struct sockaddr*)&svrAddr, sizeof(svrAddr)) ){
closesocket( sock );
return -5;//连接代理服务器失败
}

m_proxyreq1 = (LPREQ1_SOCK5)buf;
m_proxyreq1->Ver = 5;
m_proxyreq1->nMethods = 2;
m_proxyreq1->Methods[0] = 0x0;
m_proxyreq1->Methods[1] = 0x2;

if( send(sock, buf, sizeof(REQ1_SOCK5), 0 ) < 1 ){
closesocket( sock );
return -102;//第一次请求代理服务器交互出错
}


m_proxyans1 = (LPANS1_SOCK5)buf;
ZeroMemory( m_proxyans1, sizeof(ANS1_SOCK5) );
if ( WaitSomeTime(sock, 60, RECV) == 1){
cbRecv = recv(sock, buf, sizeof(ANS1_SOCK5) ,0 );
}else{
closesocket( sock );
return -103; //接收代理服务器第一次响应出错
}

if (cbRecv<1) {
closesocket( sock );
return -104;
}
if(m_proxyans1->Ver != 0x5 || (m_proxyans1->Method!=0 && m_proxyans1->Method!=2)){
closesocket( sock );
return -6; //代理服务器不支持socket5
}

if(m_proxyans1->Method == 0x2){
cbSend = 0;
buf[cbSend++] = 0x1;

buf[cbSend++]= (char)iProxyAccountLen;
memcpy( buf+cbSend, lpszProxyAccount, iProxyAccountLen );
cbSend += iProxyAccountLen;

buf[cbSend++]= (char)iProxyPwdLen;
memcpy( buf+cbSend, lpszProxyPwd, iProxyPwdLen );
cbSend += iProxyPwdLen;

if ( send(sock, buf, cbSend , 0) < 1){
closesocket( sock );
return -110;//验证请求代理服务器交互出错
}

m_authans = (LPANS_AUTHEN_SOCK5)buf;
ZeroMemory( m_authans, sizeof(ANS_AUTHEN_SOCK5) );
if (WaitSomeTime(sock, 60, RECV) == 1)
cbRecv = recv(sock, buf, 100,0);
else{
closesocket( sock );
return -111; ///验证请求代理服务器交互出错
}

if( m_authans->Ver != 1 || m_authans->Status != 0)
{
closesocket( sock );
return -112; //代理服务器用户验证失败
}
}


// VER:1字节,协议版本号码,这里是 X'05'。
// CMD:1字节,SOCKS命令字,其意义如下。
// 连结请求(CONNECT),值为:X'01'
// 绑定请求(BIND),值为:X'02'
// UDP关联请求(UDP ASSOCIATE),值为:X'03'
// RSV:1字节,保留备用。
// ATYP:1字节,所用的地址类型,如下。
// IPV4地址(IPV4): X'01'
// 域名(DOMAINNAME): X'03'
// IPV6地址(IPV6): X'04'
// DST.ADDR:长度可变,客户机期望连结的目的主机地址。
// DST.PORT:2字节,客户机期望的目的主机应用的端口(网络字节序)

m_proxyreq2 = (LPREQ2_SOCK5)buf;
m_proxyreq2->Ver = 0x5;
m_proxyreq2->Cmd = 0x1;
m_proxyreq2->Rsv = 0x0;
m_proxyreq2->Atyp = 0x3;//域名
cbSend = 4;

int iAddrLen = strlen( lpszServerAddr )%256;
buf[cbSend++] = (char)iAddrLen;
memcpy( buf + cbSend, lpszServerAddr, iAddrLen );
cbSend += iAddrLen;


buf[cbSend++] = (char)( nServerPort>>8 );
buf[cbSend++] = (char)( nServerPort%255 );

if ( send( sock, buf, cbSend, 0 ) < 1 ){
closesocket( sock );
return -113;//验证请求代理服务器交互出错
}

m_proxyans2 = (LPANS2_SOCK5)buf;
ZeroMemory( buf, sizeof(ANS2_SOCK5) );
if (WaitSomeTime(sock, 60, RECV) == 1)
cbRecv = recv(sock, buf, 100,0);
else{
closesocket( sock );
return -114; ///验证请求代理服务器交互出错
}

if(m_proxyans2->Ver != 5 || m_proxyans2->Rep != 0){
closesocket( sock );
return -115;//通过代理连接主站不成功!
}

return sock;

}
cfans_2011 2010-12-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 fishion 的回复:]
CInternetSession mySession(NULL,0);//建立会话
CHttpFile* myHttpFile=NULL;

//将网页内容的源代码读至编辑框
CString myData;
myHttpFile=(CHttpFile*)mySession.OpenURL(host_name);

while(myHttpFile->ReadString(myData……
[/Quote]
------------------------
非代理方式,测试了几个是可以获取到公网IP的。。。
fishion 2010-12-14
  • 打赏
  • 举报
回复
CInternetSession mySession(NULL,0);//建立会话
CHttpFile* myHttpFile=NULL;

//将网页内容的源代码读至编辑框
CString myData;
myHttpFile=(CHttpFile*)mySession.OpenURL(host_name);

while(myHttpFile->ReadString(myData))
{
m_SiteInfo=m_SiteInfo+"\r\n";
m_SiteInfo+=myData;
}

myHttpFile->Close ;
mySession.Close ;


这样能讲到数据不
cfans_2011 2010-12-14
  • 打赏
  • 举报
回复
测试直接在IE打开http://www.ip138.com/ip2city.asp
能够获取到代理服务器的IP地址。

引用一个WebBrowse控件,
可以用这个控件加载这个页面,
是否可以继续用这个控件的相关函数,获取页面的源代码,
然后解析其中的IP。

不知道这样是否可以实现?
Eleven 2010-12-14
  • 打赏
  • 举报
回复
tracert www.xxx.com 命令中就有你的公网IP地址
zzw820626 2010-12-14
  • 打赏
  • 举报
回复
通过代理的就算是获取也是获取的代理的IP,有啥意思?
本课程目前总计105课时,并且不定期的进行新知识点的补充,目的是打造一部围绕MySQL的全体系课程。课程涵盖11大章节,分别是:第1章基础&技巧:这部分的重点是会讲解一些容易被开发人员忽略的技巧,例如utf8mb4字符集问题、如何使用外部临时表提高查询效率、快速创建同结构表及快速复制数据、截断表和删除数据使用和差异、以及怎样使用help语句查看帮助文档。第2章六大数据类型:这部分的重点是对MySQL的8种数字类型、5种日期和时间类型、10种字符串类型、枚举类型、集合类型和时间戳类型的区别和使用进行深入讲解。第3章数据库函数大全:MySQL中有上百种函数之多,使用函数可以快速的解决我们很多开发问题,但是由于我们掌握的函数不够多,往往没有办法实际应用,本章节重点是让你掌握更多好用而你不知道的函数使用。第4章数据库引擎精讲:本章节带您深入到MySQL的体系架构,深入理解innoDB、MyISAM、MEMORY、ARCHIVE引擎的区别和使用原则。第5章数据库索引精讲:索引是保障我们查询效率的重点,本章节从逻辑存储和物理存储的底层入手,深入剖析索引的存储结构和查找方法,掌握聚簇索引、非聚簇索引、前缀索引等的存取原理和使用技巧。第6章调优工具:工欲善其事必先利其器,本章节带你掌握读写比例查询、缓存设置、执行计划和Profile调优工具。第7章参数调优和索引调优:怎么样让SQL执行的更快、数据库的性能更强,怎样充分利用索引进行不断的优化。本章节会为您讲解16种MySQL的优化策略。第8章SQL调优:SQL语句是我们日常使用的重点,怎么样写出一手高性能的SQL语句,其实是具有一定技巧的,本章节讲解8种优化策略,让数据SQL执行性能更强。第9章分库分表:在面对海量数据的时候单表和单个数据库的性能始终会存在瓶颈,本章节为您讲解分库分表的原理和技巧,怎么样使用Merge引擎分表、深入掌握MySQL数据库分区表的能力。第10章高可用架构和安全管理:本部分涵盖MySQL的高可用架构,主备架构、主从架构、主从从架构、互为主从架构。数据的同步复制、半同步复制、异步复制。主从复制原理和主从延迟的问题,以及在管理和开发层面怎样保证数据库安全。第11章MySQL日志:对MySQL的7种日志进行讲解,包括errorlog错误日志、general log查询日志、slow log慢日志、binlog 二进制日志、redlog重做日志。课程会附带配套文档和SQL脚本。有问题可以直接联系作者,24小时线上答疑。

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧