c++ http請求


平常我們要訪問某個URL一般都是通過瀏覽器進行:提交一個URL請求后,瀏覽器將請求發向目標服務器或者代理服務器,目標服務器或者代理服務器返回我們所需要的數據,瀏覽器接收到這些數據后保存成文件並進行顯示。
下面我們看看如何自己利用winsock2.h中的接口來實現這個功能?為了簡化問題,作以下假設:
通過代理服務器進行HTTP訪問,這樣就省去了對URL進行DNS解析的步驟,假設代理服務器的地址為: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,&amp;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。
 
基本就是上面這些,這四個問題解決了,那么整個問題也就解決了!
文章出處:DIY部落(http://www.diybl.com/course/3_program/c++/cppsl/2008227/101925.html)

另外一個帖子

c socket 發送http請求
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(){
int sockfd;
int len;
struct sockaddr_in address;
int result;
char *strings="GET /svnup/rewrite.php HTTP/1.1\r\nHost: 192.168.1.12\r\nConnection: Close\r\n\r\n";
char ch;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("192.168.1.12");
address.sin_port = htons(80);
len = sizeof(address);
result = connect(sockfd,  (struct sockaddr *)&address, len);
if(result == -1){
    perror("oops: client1");
    return 1;
}
write(sockfd,strings,strlen(strings));
while(read(sockfd,&ch,1))
    printf("%c", ch);
close(sockfd);
return 1;
}

“如何利用socket進行HTTP訪問”的更多相關文章 》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM