C++如何监听http请求
生活随笔
收集整理的這篇文章主要介紹了
C++如何监听http请求
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
下面有個例子,基于?Windows?的,編譯完,運行?:?WebSrv?7070?即可。在程序的目錄中放一個?index.html?文件。/**************************************************************************?*?Copyright?(c)?2002-2005?by?Zhang?Huiyong?All?Rights?Reserved**?FILENAME:??WebSrv.c**?PURPOSE?:??HTTP?服務器程序,?向客戶端提供請求的文件內容.*??*?AUTHOR??:??張會勇*?*?BOOK????:??<<WinSock網絡編程經絡>>*?**************************************************************************/#include?<stdio.h>
#include?<winsock2.h>#pragma?comment(lib,?"ws2_32.lib")??/*?WinSock使用的庫函數?*//*?定義常量?*/
#define?HTTP_DEF_PORT????????80?????/*?連接的缺省端口?*/
#define?HTTP_BUF_SIZE??????1024?????/*?緩沖區的大小?*/
#define?HTTP_FILENAME_LEN???256?????/*?文件名長度?*//*?定義文件類型對應的?Content-Type?*/
struct?doc_type
{char?*suffix;?/*?文件后綴?*/char?*type;???/*?Content-Type?*/
};struct?doc_type?file_type[]?=?
{{"html",????"text/html"??},{"gif",?????"image/gif"??},{"jpeg",????"image/jpeg"?},{?NULL,??????NULL????????}
};char?*http_res_hdr_tmpl?=?"HTTP/1.1?200?OK\r\nServer:?Huiyong's?Server?<0.1>\r\n""Accept-Ranges:?bytes\r\nContent-Length:?%d\r\nConnection:?close\r\n""Content-Type:?%s\r\n\r\n";/****************************************************************************?函數功能:?根據文件后綴查找對應的?Content-Type.**?參數說明:?[IN]?suffix,?文件名后綴;**?返?回?值:?成功返回文件對應的?Content-Type,?失敗返回?NULL.***************************************************************************/
char?*http_get_type_by_suffix(const?char?*suffix)
{struct?doc_type?*type;for?(type?=?file_type;?type->suffix;?type++){if?(strcmp(type->suffix,?suffix)?==?0)return?type->type;}return?NULL;
}/****************************************************************************?函數功能:?解析請求行,?得到文件名及其后綴.?請求行格式:*???????????[GET?http://www.baidu.com:8080/index.html?HTTP/1.1]**?參數說明:?[IN]??buf,?字符串指針數組;*???????????[IN]??buflen,?buf?的長度;*???????????[OUT]?file_name,?文件名;*???????????[OUT]?suffix,?文件名后綴;**?返?回?值:?void.***************************************************************************/
void?http_parse_request_cmd(char?*buf,?int?buflen,?char?*file_name,?char?*suffix)
{int?length?=?0;char?*begin,?*end,?*bias;/*?查找?URL?的開始位置?*/begin?=?strchr(buf,?'?');begin?+=?1;/*?查找?URL?的結束位置?*/end?=?strchr(begin,?'?');*end?=?0;bias?=?strrchr(begin,?'/');length?=?end?-?bias;/*?找到文件名的開始位置?*/if?((*bias?==?'/')?||?(*bias?==?'\\')){bias++;length--;}/*?得到文件名?*/if?(length?>?0){memcpy(file_name,?bias,?length);file_name[length]?=?0;begin?=?strchr(file_name,?'.');if?(begin)strcpy(suffix,?begin?+?1);}
}/****************************************************************************?函數功能:?向客戶端發送?HTTP?響應.**?參數說明:?[IN]??buf,?字符串指針數組;*???????????[IN]??buf_len,?buf?的長度;**?返?回?值:?成功返回非0,?失敗返回0.***************************************************************************/
int?http_send_response(SOCKET?soc,?char?*buf,?int?buf_len)
{int?read_len,?file_len,?hdr_len,?send_len;char?*type;char?read_buf[HTTP_BUF_SIZE];char?http_header[HTTP_BUF_SIZE];char?file_name[HTTP_FILENAME_LEN]?=?"index.html",?suffix[16]?=?"html";FILE?*res_file;/*?得到文件名和后綴?*/http_parse_request_cmd(buf,?buf_len,?file_name,?suffix);res_file?=?fopen(file_name,?"rb+");?/*?用二進制格式打開文件?*/if?(res_file?==?NULL){printf("[Web]?The?file?[%s]?is?not?existed\n",?file_name);return?0;}fseek(res_file,?0,?SEEK_END);file_len?=?ftell(res_file);fseek(res_file,?0,?SEEK_SET);type?=?http_get_type_by_suffix(suffix);?/*?文件對應的?Content-Type?*/if?(type?==?NULL){printf("[Web]?There?is?not?the?related?content?type\n");return?0;}/*?構造?HTTP?首部,并發送?*/hdr_len?=?sprintf(http_header,?http_res_hdr_tmpl,?file_len,?type);send_len?=?send(soc,?http_header,?hdr_len,?0);if?(send_len?==?SOCKET_ERROR){fclose(res_file);printf("[Web]?Fail?to?send,?error?=?%d\n",?WSAGetLastError());return?0;}do?/*?發送文件,?HTTP?的消息體?*/{read_len?=?fread(read_buf,?sizeof(char),?HTTP_BUF_SIZE,?res_file);if?(read_len?>?0){send_len?=?send(soc,?read_buf,?read_len,?0);file_len?-=?read_len;}}?while?((read_len?>?0)?&&?(file_len?>?0));fclose(res_file);return?1;
}int?main(int?argc,?char?**argv)
{WSADATA?wsa_data;SOCKET srv_soc?=?0,?acpt_soc;??/*?socket?句柄?*/ struct?sockaddr_in?serv_addr;???/*?服務器地址??*/struct?sockaddr_in?from_addr;???/*?客戶端地址??*/char?recv_buf[HTTP_BUF_SIZE];unsigned?short?port?=?HTTP_DEF_PORT;unsigned?long?from_len?=?sizeof(from_addr);int result?=?0,?recv_len;if?(argc?==?2)?/*?端口號?*/port?=?atoi(argv[1]);WSAStartup(MAKEWORD(2,0),?&wsa_data);?/*?初始化?WinSock?資源?*/srv_soc?=?socket(AF_INET,?SOCK_STREAM,?0);?/*?創建?socket?*/if?(srv_soc?==?INVALID_SOCKET){printf("[Web]?socket()?Fails,?error?=?%d\n",?WSAGetLastError());return?-1;?}/*?服務器地址?*/serv_addr.sin_family?=?AF_INET;serv_addr.sin_port?=?htons(port);serv_addr.sin_addr.s_addr?=?htonl(INADDR_ANY);result?=?bind(srv_soc,?(struct?sockaddr?*)?&serv_addr,?sizeof(serv_addr));if?(result?==?SOCKET_ERROR)?/*?綁定失敗?*/{closesocket(srv_soc);printf("[Web]?Fail?to?bind,?error?=?%d\n",?WSAGetLastError());return?-1;?}result?=?listen(srv_soc,?SOMAXCONN);printf("[Web]?The?server?is?running?...?...\n");while?(1){acpt_soc?=?accept(srv_soc,?(struct?sockaddr?*)?&from_addr,?&from_len);if?(acpt_soc?==?INVALID_SOCKET)?/*?接受失敗?*/{printf("[Web]?Fail?to?accept,?error?=?%d\n",?WSAGetLastError());break;?}printf("[Web]?Accepted?address:[%s],?port:[%d]\n",?inet_ntoa(from_addr.sin_addr),?ntohs(from_addr.sin_port));recv_len?=?recv(acpt_soc,?recv_buf,?HTTP_BUF_SIZE,?0);if?(recv_len?==?SOCKET_ERROR)?/*?接收失敗?*/{closesocket(acpt_soc);printf("[Web]?Fail?to?recv,?error?=?%d\n",?WSAGetLastError());break;?}recv_buf[recv_len]?=?0;/*?向客戶端發送響應數據?*/result?=?http_send_response(acpt_soc,?recv_buf,?recv_len);closesocket(acpt_soc);}closesocket(srv_soc);WSACleanup();printf("[Web]?The?server?is?stopped.\n");return?0;
}
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的C++如何监听http请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++函数返回值与引用
- 下一篇: c/c++实现一个密集型server/s