為了幫網友些個用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; }
|