zoukankan      html  css  js  c++  java
  • 用VC++实现http代理

    为了帮网友些个用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 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断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/adodo1/p/4327775.html
Copyright © 2011-2022 走看看