基於visual c++之windows核心編程程式碼分析(32)HTTP協議編程

來源:互聯網
上載者:User

超文本傳送協議 (HTTP) 是一種通訊協定,它允許將超文字標記語言 (HTML) (HTML) 文檔從 Web 服務器傳送到 網頁瀏覽器。HTML 是一種用於建立文檔的標記語言,這些文檔包含到相關資訊的連結。您可以單擊一個連結來訪問其它文檔、映像或多媒體對象,並獲得關於連結項的附加資訊。   客戶機和伺服器必須都支援 HTTP,才能在全球資訊網上發送和接收 HTML 文檔並進行互動。  

 HTTP是一個屬於應用程式層的物件導向的協議,由於其簡捷、快速的方式,適用於分布式超媒體資訊系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴充。目前在WWW中使用的是HTTP/1.0的第六版,特別是在Proxy 伺服器中。HTTP/1.1的正常化工作進行中之中,持久串連被預設採用,並能很好地配合Proxy 伺服器工作。而且HTTP-NG(Next Generation of HTTP)的建議已經提出。
  HTTP協議的主要特點可概括如下:

  支援客戶/伺服器模式。 簡單快速:客戶向伺服器請求服務時,只需傳送要求方法和路徑。要求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯絡的類型不同。由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。 靈活:HTTP允許傳輸任意類型的資料對象。正在傳輸的類型由Content-Type加以標記。 無串連:不需連線的含義是限制每次串連只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即中斷連線。採用這種方式可以節省傳輸時間。 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於交易處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次串連傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。

我們來親自用VC++實現http協議

 

#include <stdio.h> #include <winsock2.h> #define  MAXBUFLEN  20480 #define  HTTPADDLEN 50 #define  TIMEWAIT   2000 #pragma comment(lib,"ws2_32.lib")SOCKET   Global[1000]; DWORD WINAPI  Proxy( LPVOID pSocket); int   ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr); int main(int argc,char * argv[]) {    SOCKET  MainSocket,ClientSocket;    struct  sockaddr_in Host,Client;    WSADATA WsaData;    int  AddLen,i;    //初始化       if(WSAStartup(MAKEWORD(2,2),&WsaData) < 0)    {        printf("初始化失敗\n");        return 1;    }    //建立socket連接埠    MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);    if(MainSocket == SOCKET_ERROR)    {        printf("連接埠建立錯誤\n");   return 1;   }    Host.sin_family = AF_INET;    Host.sin_port = htons(8080);    Host.sin_addr.s_addr = inet_addr("127.0.0.1");    printf("正在工作\n");    //綁定socket   if(bind(MainSocket,(SOCKADDR *)&Host,sizeof(Host)) != 0)    {        printf("綁定錯誤\n");   }    i = 0;    //監聽    if(listen(MainSocket,5) == SOCKET_ERROR)    {        printf("監聽錯誤\n");    }    AddLen = sizeof(Client);    //串連新的客戶    i = 0;    for(;;)    {        ClientSocket = accept(MainSocket,(SOCKADDR *)&Client,&AddLen);        if(ClientSocket == SOCKET_ERROR)        {            printf("接受客戶請求錯誤!\n");        }        printf(".");        i ++ ;        if( i >= 1000)            i = 0;        Global[i] = ClientSocket;        //對於每一個客戶啟動不同的線程程進行控制        //這個地方在使用ClientSocket的時候,要不要保證在某一時刻內只能有一個進程使用?        CreateThread(NULL,0,Proxy,(LPVOID)Global[i],0,NULL);           }     return 0;} DWORD WINAPI Proxy( LPVOID pSocket) {    SOCKET ClientSocket;    char  ReceiveBuf[MAXBUFLEN];    int  DataLen;    struct sockaddr_in  ServerAddr;    SOCKET  ProxySocket;    int i = 0;    int time = TIMEWAIT;    //得到參數中的連接埠號碼資訊    ClientSocket = (SOCKET)pSocket; //接受第一次請求資訊    memset(ReceiveBuf,0,MAXBUFLEN);    DataLen = recv(ClientSocket,ReceiveBuf,MAXBUFLEN,0);    if(DataLen == SOCKET_ERROR)    {        printf("錯誤\n");        closesocket(ClientSocket);       return 0;   }    if(DataLen == 0)    {        closesocket(ClientSocket);       return 0;   }        //處理請求資訊,分離出伺服器位址    if( ParseHttpRequest(ReceiveBuf,DataLen,(void *)&ServerAddr) < 0)    {        closesocket(ClientSocket);        goto error;    }    //建立新的socket用來和伺服器進行串連    ProxySocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);    //設定逾時時間    setsockopt(ProxySocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&time,sizeof(time));    if(ProxySocket == SOCKET_ERROR)    {        printf("連接埠建立錯誤\n");        return 0;   }    if(connect(ProxySocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR)    {        //printf("串連伺服器錯誤");        goto error;    }    //開始進行資料轉送處理    //發送到伺服器端    if(send(ProxySocket,ReceiveBuf,DataLen,0) == SOCKET_ERROR)    {        //printf("資料發送錯誤");        goto error;    }        //從伺服器端接受資料    while(DataLen > 0)    {        memset(ReceiveBuf,0,MAXBUFLEN);            if((DataLen = recv(ProxySocket,ReceiveBuf,MAXBUFLEN,0)) <= 0)        {            //    printf("資料接受錯誤");            break;                    }        else            //發送到用戶端            if(send(ClientSocket,ReceiveBuf,DataLen,0) < 0)            {                //    printf("資料發送錯誤");                    break;            }            }     error:    closesocket(ClientSocket);    closesocket(ProxySocket);    return 0; } int  ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr) {    char * HttpHead = "http://";    char * FirstLocation = NULL;    char * LastLocation = NULL;    char * PortLocation = NULL;    char  ServerName[HTTPADDLEN];    char  PortString[10];    int   NameLen;    struct hostent * pHost;    struct sockaddr_in * pServer = (struct sockaddr_in *)ServerAddr;    //取得http://的位置    FirstLocation = strstr(SourceBuf,HttpHead) + strlen(HttpHead);    //取得/的位置    printf("%s\n",FirstLocation);   LastLocation=strstr(FirstLocation,"/");    //得到http://和/之間的伺服器的名稱        memset(ServerName,0,HTTPADDLEN);    memcpy(ServerName,FirstLocation,LastLocation - FirstLocation);    //有些情況下,請求的地址中帶有連接埠號碼格式為“:+ 連接埠號碼”;    //取得 :的位置    PortLocation = strstr(ServerName,":");        //填充server結構    pServer->sin_family = AF_INET;    //在url中制定了伺服器連接埠    if(PortLocation != NULL)    {        NameLen = PortLocation - ServerName -1;        memset(PortString,0,10);        memcpy(PortString,PortLocation + 1,NameLen);        pServer->sin_port = htons((u_short)atoi(PortString));        *PortLocation = 0;        }    else//在url中,沒有制定伺服器連接埠    {        pServer->sin_port=htons(80);    }    if(NameLen > HTTPADDLEN)    {        printf("伺服器名字太長\n");        return -1;    }        //得到伺服器資訊    //如果地址資訊是以IP地址(192.168.0.1)的形式出現的    if(ServerName[0] >= '0' && ServerName[0] <= '9')    {                pServer->sin_addr.s_addr = inet_addr(ServerName);    }    //以網域名稱的形式出現的(www.sina.com.cn)    else    {        pHost = (struct hostent *)gethostbyname(ServerName);        if(!pHost)        {            printf("取得主機資訊錯誤\n");            printf("%s\n",ServerName);            return -1;        }        memcpy(&pServer->sin_addr,pHost->h_addr_list[0],sizeof(pServer->sin_addr));    }        return 0; } 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.