透過代理看世界 用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<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();

}

}

基本就是這樣了,本人寫程序水平也不是很高,這個程序還是可以用的。

透過代理看世界 用VC++實現http代理
更多內容請看HTTP協議專題,或

用VC++實現http代理
  爲了幫網友些個用http下載動畫的程序,臨時在網上翻了翻,看看有沒有利用http代理來下載的例子。結果,似乎很多人都願意去轉載一個有頭無尾的例子,還美其名曰“我在查閱RFC文檔和相關資料後,特總結一些TCP協議...查看完整版>>用VC++實現http代理
 
透過代理看世界(http代理篇)
爲了幫網友些個用http下載動畫的程序,臨時在網上翻了翻,看看有沒有利用http代理來下載的例子。結果,似乎很多人都願意去轉載一個有頭無尾的例子,還美其名曰“我在查閱RFC文檔和相關資料後,特總結一些TCP協議...查看完整版>>透過代理看世界(http代理篇)
 
用 VC++ 和 Winsock 實現與 HTTP 服務器通話
用 VC++ 和 Winsock 實現與 HTTP 服務器通話 作者:Ji Hong 一、引 言 ---- Windows Socket API是一套開放的、支持多種協議的Windows下的網絡編程接口,它包 括一個標准的 Berkeley Socket功能調用的集合,以及爲Win...查看完整版>>用 VC++ 和 Winsock 實現與 HTTP 服務器通話
 
通過HTTP代理實現SOCKS代理功能的SOCKS2HTTP教程
  一、前言  在上網沖浪的過程中,你想隱藏你的來源,提供給別人一非你本機的ip地址?簡單的方法就是使用代理(PRoxy)。代理服務主機一般由企業等團體建立,提供內部網絡訪問Internet的代理服務,代理服務器的作...查看完整版>>通過HTTP代理實現SOCKS代理功能的SOCKS2HTTP教程
 
Visual C#實現HTTP代理服務程序
  網絡代理程序的種類非常多,根據代理服務程序代理的協議不同,分成HTTP代理服務程序、FTP代理服務程序等,運行代理服務程序的服務器也就稱爲HTTP代理服務器和FTP代理服務器。在本節中介紹的Web代理服務程序代理的...查看完整版>>Visual C#實現HTTP代理服務程序
 
VC++下用MSComm控件實現串口通訊
首先,在對話框中創建通信控件,若Control工具欄中缺少該控件,可通過菜單Project --> Add to Project --> Components and Control插入即可,再將該控件從工具箱中拉到對話框中。此時,你只需要關心控件提供的...查看完整版>>VC++下用MSComm控件實現串口通訊
 
利用VC++編程實現程序自動啓動
工作中經常碰到一些程序,它們在系統啓動的過程中,自動打開並運行,以便實現對系統的監控或者病毒的檢測等特定的目的,典型的例子就是常用的一些殺毒軟件如:KV300及瑞星殺毒軟件等。筆者在此,以自己的編程實踐爲基...查看完整版>>利用VC++編程實現程序自動啓動
 
VC++實現Win2000下直接讀寫磁盤扇區
VC++實現Win2000下直接讀寫磁盤扇區
引言由于Windows 操作系統在很大程度上采取了訪問安全保護機制(例如,在Windows操作系統下不能直接訪問物理內存、不能使用各種DOS、BIOS中斷等等),使得廣大程序設計人員在長時間的開發過程中不知不覺地逐漸養成了...查看完整版>>VC++實現Win2000下直接讀寫磁盤扇區
 
VC++實現COM事件接收器
1、給程序添加ATL支持。 右鍵->New ATL Object2、實現IDispEventImpl 接口。//EventSink.h#import "..\Server\Debug\Server.exe" raw_interface_only,no_namespace,named_guidsclass CEventSink ...查看完整版>>VC++實現COM事件接收器
 
 
回到王朝網路移動版首頁