王朝网络
分享
 
 
 

透过代理看世界 用VC++实现http代理

王朝vc·作者佚名  2008-06-01
宽屏版  字体: |||超大  

为了帮网友些个用http下载动画的程序,临时在网上翻了翻,看看有没有利用http代理来下载的例子。结果,似乎很多人都愿意去转载一个有头无尾的例子,还美其名曰“我在查阅RFC文档和相关资料后,特总结一些TCP协议穿透代理服务器的程序片断,希望对大家有所帮助。”

假如真的想帮助大家,为什么不说的具体一些?

无奈之下,自己去翻rfc文档,找了些资料,写了这个利用http代理来下载文件的资料

代码如下:

(1)一些基本变量

SOCKET HTTPSocket; // 主socket

strUCt sockaddr_in SocketAddr; // address socket

struct sockaddr_in BindSocket; // for bind

int m_nRecvTimeout; // recieve timeout

int m_nSendTimeout; // send timeout

WSADATA wsaData;

// 要下载文件部分。似乎在BindSocket.sin_addr.s_addr = inet_addr (strHost);时,只能使用ip地址,所以了。。。

// 假如谁知道更好的方法,别忘了告诉我一下。

CString strHost="111.111.111.111 ";

CString DownLoadAddress="http://www.aitenshi.com/bbs/images/";

CString hostFile="logo.gif";

int HttpPort=80;

(2)一些函数,用来取得http头,和获取文件大小

int GetFileLength(char *httpHeader)

{

CString strHeader;

int local;

strHeader=(CString)httpHeader;

local=strHeader.Find("Content-Length",0);

local+=16;

strHeader.Delete(0,local);

local=strHeader.Find("\r");

strHeader.SetAt(local,'\0');

char temp[30];

strcpy(temp,strHeader.GetBuffer(strHeader.GetLength()));

return atoi(temp);

}

int GetHttpHeader(SOCKET sckDest,char *str)

{

BOOL m_bResponsed=0;

int m_nResponseHeaderSize;

if(!m_bResponsed)

{

char c = 0;

int nIndex = 0;

BOOL bEndResponse = FALSE;

while(!bEndResponse && nIndex < 1024)

{

recv(sckDest,&c,1,0);

str[nIndex++] = c;

if(nIndex >= 4)

{

if(str[nIndex - 4] == '\r' && str[nIndex - 3] == '\n'

&& str[nIndex - 2] == '\r' && str[nIndex - 1] == '\n')

bEndResponse = TRUE;

}

}

m_nResponseHeaderSize = nIndex;

m_bResponsed = TRUE;

}

return m_nResponseHeaderSize;

}

(3)用来发送的部分

void szcopy(char* dest,const char* src,int nMaxBytes)

{

int i_cntr=0;

while ((src[i_cntr]!='\0') (i_cntr<nMaxBytes))

dest[i_cntr]=src[i_cntr++];

dest[i_cntr]='\0';

}

BOOL SocketSend(SOCKET sckDest,const char* szHttp)

{

char szSendHeader[MAXHEADERLENGTH];

int iLen=strlen(szHttp);

szcopy(szSendHeader,szHttp,iLen);

if(send (sckDest ,(const char FAR *)szSendHeader ,iLen ,0)==SOCKET_ERROR)

{

closesocket(sckDest);

AfxMessageBox("Error when send");

return FALSE;

}

return TRUE;

}

BOOL SocketSend(SOCKET sckDest,CString szHttp)

{

int iLen=szHttp.GetLength();

if(send (sckDest,szHttp,iLen,0)==SOCKET_ERROR)

{

closesocket(sckDest);

AfxMessageBox("Error when send");

return FALSE;

}

return TRUE;

}

(4)用于连接的函数

这里是做了一些连接用的操作,分了两种情况

1)假如没有使用代理,则直接连到你指定的计算机

2)假如使用了代理,则直接连到代理

BOOL CDLAngelDlg::ConnectHttp()

{

message="正在建立连接\n";

UpdateData(TRUE);

if(m_combo=="HTTP") // m_combo 一个下拉条

{

HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

SocketAddr.sin_addr.s_addr = inet_addr (m_ProxyAddr);

SocketAddr.sin_family=AF_INET;

SocketAddr.sin_port=htons(atoi(m_Port));

struct fd_set fdSet;

struct timeval tmvTimeout={0L,0L};

FD_ZERO(&fdSet);

FD_SET(HTTPSocket, &fdSet);

if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)

{

closesocket(HTTPSocket);

AfxMessageBox("Error when select.");

return 0;

}

if (connect(HTTPSocket, (const struct sockaddr *)&SocketAddr, sizeof(SocketAddr))==SOCKET_ERROR)

{

message="\n代理连接失败\n";

m_message.CleanText();

m_message.AddText(message);

return 0;

}

// 发送CONNCET请求令到代理服务器,用于和代理建立连接

//代理服务器的地址和端口放在m_ProxyAddr,m_Port 里面

CString temp;

char tmpBuffer[1024];

temp.Format("CONNECT %s:%s HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n",m_ProxyAddr,m_Port);

if(!SocketSend(HTTPSocket,temp))

{

message="连接代理失败";

return 0;

}

// 取得代理响应,假如连接代理成功,代理服务器将返回200 Connection established

GetHttpHeader(HTTPSocket,tmpBuffer);

temp=tmpBuffer;

if(temp.Find("HTTP/1.0 200 Connection established",0)==-1)

{

message="连接代理失败\n";

return 0;

}

message="代理连接完成\n";

m_message.AddText("代理连接完成\n");

return 1; // ----------〉这里是应该注重的,连接到代理后,就可以返回了,不需要再连接网上的另外一台机,代理服务器会自动转发数据,所以,连接完代理就像连接到网上另外一台机一样

}

// 这个,是为了给其他代理做预备

else if(m_combo=="Socks4")

{MessageBox("请注重,现在无法使用代理功能!");}

else if(m_combo=="Socks5")

{MessageBox("请注重,现在无法使用代理功能!");}

// 假如没有使用代理,就要连接到网上的另一台机

// 预备socket

HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

if (HTTPSocket==INVALID_SOCKET)

{

AfxMessageBox("Error when socket");

return 0;

}

//设置超时

struct linger zeroLinger;

zeroLinger.l_onoff = 1;

zeroLinger.l_linger = 0;

if(setsockopt(HTTPSocket,SOL_SOCKET,SO_LINGER

,(const char *)&zeroLinger

,sizeof(zeroLinger))!=0)

{

closesocket(HTTPSocket);

AfxMessageBox("Error when setscokopt(LINGER)");

return 0;

}

//设置接收超时

if(setsockopt(HTTPSocket,SOL_SOCKET,SO_RCVTIMEO

,(const char *)&m_nRecvTimeout

,sizeof(m_nRecvTimeout))!=0)

{

closesocket(HTTPSocket);

AfxMessageBox("Error when setsockopt(RCVTIME).");

return 0;

}

//设置发送超时

if(setsockopt(HTTPSocket,SOL_SOCKET,SO_SNDTIMEO

,(const char *)&m_nSendTimeout

,sizeof(m_nSendTimeout))!=0)

{

closesocket(HTTPSocket);

AfxMessageBox("Error when setsockopt(SNDTIMEO).");

return 0;

}

SocketAddr.sin_addr.s_addr = htonl (INADDR_ANY);

SocketAddr.sin_family=AF_INET;

// 进行端口绑定

if (bind (HTTPSocket,

(const struct sockaddr FAR *)&SocketAddr,

sizeof(SocketAddr))==SOCKET_ERROR)

{

closesocket(HTTPSocket);

AfxMessageBox("Error when bind socket.");

return 0;

}

//预备连接

/// 预备连接信息

BindSocket.sin_addr.s_addr = inet_addr (strHost);

BindSocket.sin_family=AF_INET;

BindSocket.sin_port=htons(HttpPort);

struct fd_set fdSet;

struct timeval tmvTimeout={0L,0L};

FD_ZERO(&fdSet);

FD_SET(HTTPSocket, &fdSet);

if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)

{

closesocket(HTTPSocket);

AfxMessageBox("Error when select.");

return 0;

}

// 连接

if (connect(HTTPSocket, (const struct sockaddr *)&BindSocket, sizeof(BindSocket))==SOCKET_ERROR)

{

AfxMessageBox("第一次连接失败,预备第二次连接");

if (connect(HTTPSocket

,(const struct sockaddr *)&BindSocket

,sizeof(BindSocket))==SOCKET_ERROR)

{

closesocket(HTTPSocket);

AfxMessageBox("连接失败");

return 0;

}

}

message="连接完成\n";

return 1;

}

(5)发送http请求,为下载数据进行预备

int CDLAngelDlg::SendHttpHeader()

{

//进行下载

CString temp;

BOOL bReturn;

char tmpBuffer[MAXBLOCKSIZE];

///第1行:方法,请求的路径,版本

temp="GET "+DownLoadAddress+hostFile+" HTTP/1.0\r\n";

bReturn=SocketSend(HTTPSocket,temp);

if(!bReturn)

{

message="发送请求失败";

return 0;

}

///第2行:主机

temp="Host "+strHost+"\r\n";

bReturn=SocketSend(HTTPSocket,temp);

if(!bReturn)

{

message="发送请求失败";

return 0;

}

///第3行:接收的数据类型

bReturn=SocketSend(HTTPSocket,"Accept: */*\r\n");

if(!bReturn)

{

message="发送请求失败";

return 0;

}

///第4行:

temp=DownLoadAddress;

temp.Insert(0,"Referer ");

temp+="\r\n";

bReturn=SocketSend(HTTPSocket,temp);

if(!bReturn)

{

message="发送请求失败";

return 0;

}

///第5行:浏览器类型

bReturn=SocketSend(HTTPSocket,"User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DTS Agent;)\r\n");

if(!bReturn)

{

message="发送请求失败";

return 0;

}

///第6行:连接设置,保持

// SocketSend(HTTPSocket,"Connection:Keep-Alive\r\n");

///第7行:Cookie.

bReturn=SocketSend(HTTPSocket,"Cache-Control: no-cache\r\n");

if(!bReturn)

{

message="发送请求失败";

return 0;

}

bReturn=SocketSend(HTTPSocket,"Proxy-Connection: Keep-Alive\r\n");

if(!bReturn)

{

message="发送请求失败";

return 0;

}

/// 续传

Range是要下载的数据范围,对续传很重要

if(continueFlag)

{

temp.Format("Range: bytes=%d- \r\n",conLength);

bReturn=SocketSend(HTTPSocket,temp);

if(!bReturn)

{

message="发送请求失败";

return 0;

}

}

///最后一行:空行

bReturn=SocketSend(HTTPSocket,"\r\n");

if(!bReturn)

{

message="发送请求失败";

return 0;

}

///取得http头

int i;

i=GetHttpHeader(HTTPSocket,tmpBuffer);

if(!i)

{

message="获取HTTP头出错";

return 0;

}

//假如取得的http头含有404等字样,则表示连接出问题

temp=tmpBuffer;

if(temp.Find("404")!=-1)

{

return 0;

}

// 得到待下载文件的大小

filelength=GetFileLength(tmpBuffer);

return 1;

}

这样,就连接到网上的另一台机了,如何下载数据,不用多说了吧

while((num!=SOCKET_ERROR) && (num!=0))

{

num=recv (HTTPSocket

,(char FAR *)tmpBuffer

,(MAXBLOCKSIZE-1)

,0);

file.Write(tmpBuffer,num);

if(ExitFlag)

{

file.Close();

closesocket(HTTPSocket);

DownComplete=1;

m_message.CleanText();

m_message.ShowColorText(RGB(128,128,0),DLCompleteMes);

m_progress.ShowWindow(SW_HIDE);

m_stopDownload.ShowWindow(SW_HIDE);

_endthread();

}

}

基本就是这样了,本人写程序水平也不是很高,这个程序还是可以用的。

更多内容请看HTTP协议专题,或

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有