如何利用socket進行HTTP訪問——————————-http://blog
來源:互聯網
上載者:User
如何利用
socket
進行
HTTP
訪問平常我們要訪問某個 URL 一般都是通過瀏覽器進行:提交一個 URL 請求後,瀏覽器將請求發向目標伺服器或者Proxy 伺服器,目標伺服器或者Proxy 伺服器返回我們所需要的資料,瀏覽器接收到這些資料後儲存成檔案並進行顯示。下面我們看看如何自己利用 winsock2.h 中的介面來實現這個功能?為了簡化問題,作以下假設:通過Proxy 伺服器進行 HTTP 訪問,這樣就省去了對 URL 進行 DNS 解析的步驟,假設Proxy 伺服器的地址為: 192.168.0.1 : 808 。 這個功能由以下幾個部分組成:1. 如何建立串連?2. 如何發送請求?3. 如何接收資料?4. 如何判斷資料接收完成? 下面我們依次來看下這些問題如何解決?
一、
如何建立與伺服器之間的串連HTTP 基本 TCP ,所以我們需要與伺服器建立串連,然後才能發送資料。建立串連參考如下函數 socket_open :/** 開啟Socket,返回socketId,-1表示失敗*/int socket_open(int IP,int Port,int type){SOCKET socketId; struct sockaddr_in serv_addr; int status; socketId=socket(AF_INET,SOCK_STREAM,0); if ((int )socketId<0) { printf("[ERROR]Create a socket failed!\n" ); return -1; } memset(&serv_addr,0,sizeof (serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr = ntohl(IP); serv_addr.sin_port = htons((USHORT)Port); status=connect(socketId,(struct sockaddr*)&serv_addr,sizeof (serv_addr)); if (status!=0) { printf("[ERROR]Connecting failed!\n" ); closesocket(socketId); return -1; } return socketId;} 調用方式如下:int socketId=socket_open( 0xC0A80001,808,0); //0xC0A80001 是192.168.0.1的十六進位寫法。
二、
如何發送請求發送資料要根據 HTTP 協議的要求附加協議頭:static const char * protocolHead="GET http://www.xxx.com/index.html HTTP/1.1\n" "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\n" "Accept-Language: zh-cn\n" "User-Agent:iPanelBrowser/2.0\n" "Host: www.xxx.com:80\n" "Connection: close\n\n" 這裡使用GET來擷取指定URL的指定文檔。 建立串連後使用send將這些資料發送出去: send(socketId, protocolHead,strlen(protocolHead),0); 發送完成HTTP請求後就等待接收資料。
三、
如何接收資料這裡採用 select 迴圈查詢的方式來判斷有無資料到來: struct timeval tm = {0,7}; fd_set fds_r; int status; char recvBuf[4096]={ ‘ \0’}; FD_ZERO(&fds_r); FD_SET(socketId,&fds_r); status=select(socketId+ 1, &fds_r, 0, 0, &tm); //socketId 在這裡是最大的fd if (status > 0 && FD_ISSET(socketId, &fds_r)){ printf("Socket is readable...fd=[%d]\n" ,socketId); recv(socketId,recvBuf,4096,0);} 這樣資料包就儲存到緩衝區中了。
四、
如何判斷資料接收完成首先對返回資料的狀態進行判斷,僅當狀態為“ HTTP 200 OK ”時才表明正確返回,這時才對資料進行解析並儲存,如果狀態為 HTTP 404 NOT FOUND 或者其它狀態則表明沒有找到資源或者出現其它問題,可參考
HTTP 1.1狀態碼及其含義 。當資料正確返回時,為了將實際資料從協議中分離出來進行儲存,需要對 HTTP 資料包進行解析得到 Content-Length ,然後在包含 Content-Length 的當前資料包或者隨後的資料包中尋找第一個空行,這就是內容( Content )的開始位置,再配合前面解析得到的 Content-Length ,就能夠知道什麼時候資料接收完成了。分行符號為“ \r\n ”,也相容“ \n ”或者“ \r ”,設分行符號為 ^P ,則空行如果位於內容中間或結尾則可尋找“ ^P^P ”,若位於開頭,則尋找 ^P 。 基本就是上面這些,這四個問題解決了,那麼整個問題也就解決了!