亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++實現簡單的HTTP服務器

2020-05-23 14:05:11
字體:
來源:轉載
供稿:網友
這篇文章主要為大家詳細介紹了C++實現簡單的HTTP服務器的相關資料,感興趣的朋友可以參考下
 

本文實例為大家分享了C++實現HTTP服務器的相關代碼,供大家參考,具體內容如下

#include <Winsock2.h>#include <windows.h>#include <malloc.h>#include <stdio.h>#include <string.h>#include <time.h> #pragma comment (lib,"ws2_32")#define uPort 80#define MAX_BUFFER   100000#define SENDBLOCK   200000#define SERVERNAME   "AcIDSoftWebServer/0.1b"#define FileName   "HelloWorld.html" typedef struct _NODE_ { SOCKET s; sockaddr_in Addr; _NODE_* pNext; }Node,*pNode;  //多線程處理多個客戶端的連接typedef struct _THREAD_{ DWORD ThreadID; HANDLE hThread; _THREAD_* pNext;}Thread,*pThread; pNode pHead = NULL;pNode pTail = NULL;pThread pHeadThread = NULL;pThread pTailThread = NULL; bool InitSocket();//線程函數DWORD WINAPI AcceptThread(LPVOID lpParam);DWORD WINAPI ClientThread(LPVOID lpParam);bool IoComplete(char* szRequest);     //數據包的校驗函數bool AddClientList(SOCKET s,sockaddr_in addr);bool AddThreadList(HANDLE hThread,DWORD ThreadID);bool ParseRequest(char* szRequest, char* szResponse, BOOL &bKeepAlive); //我們存放Html文件的目錄char HtmlDir[512]={0}; void main(){ if (!InitSocket()) {  printf("InitSocket Error/n");  return; }  GetCurrentDirectory(512,HtmlDir);  strcat(HtmlDir,"//HTML//");  strcat(HtmlDir,FileName); //啟動一個接受線程 HANDLE hAcceptThread = CreateThread(NULL,0,AcceptThread,NULL,0,NULL);  //在這里我們使用事件模型來實現我們的Web服務器 //創建一個事件 WaitForSingleObject(hAcceptThread,INFINITE);} DWORD WINAPI AcceptThread(LPVOID lpParam)   //接收線程{ //創建一個監聽套接字 SOCKET sListen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED); //使用事件重疊的套接字 if (sListen==INVALID_SOCKET) {  printf("Create Listen Error/n");  return -1;  } //初始化本服務器的地址 sockaddr_in LocalAddr; LocalAddr.sin_addr.S_un.S_addr = INADDR_ANY; LocalAddr.sin_family = AF_INET; LocalAddr.sin_port = htons(uPort); //綁定套接字 80端口 int Ret = bind(sListen,(sockaddr*)&LocalAddr,sizeof(LocalAddr)); if (Ret==SOCKET_ERROR) {  printf("Bind Error/n");  return -1; } //監聽 listen(sListen,5); //創建一個事件 WSAEVENT Event = WSACreateEvent(); if (Event==WSA_INVALID_EVENT) {  printf("Create WSAEVENT Error/n");  closesocket(sListen);  CloseHandle(Event);     //創建事件失敗 關閉套接字 關閉事件  return -1; } //將我們的監聽套接字與我們的事件進行關聯屬性為Accept WSAEventSelect(sListen,Event,FD_ACCEPT); WSANETWORKEVENTS NetWorkEvent; sockaddr_in ClientAddr; int nLen = sizeof(ClientAddr); DWORD dwIndex = 0; while (1) {  dwIndex = WSAWaitForMultipleEvents(1,&Event,FALSE,WSA_INFINITE,FALSE);  dwIndex = dwIndex - WAIT_OBJECT_0;  if (dwIndex==WSA_WAIT_TIMEOUT||dwIndex==WSA_WAIT_FAILED)  {   continue;  }  //如果有真正的事件我們就進行判斷  WSAEnumNetworkEvents(sListen,Event,&NetWorkEvent);  ResetEvent(&Event);   //  if (NetWorkEvent.lNetworkEvents == FD_ACCEPT)  {   if (NetWorkEvent.iErrorCode[FD_ACCEPT_BIT]==0)   {    //我們要為新的連接進行接受并申請內存存入鏈表中    SOCKET sClient = WSAAccept(sListen, (sockaddr*)&ClientAddr, &nLen, NULL, NULL);    if (sClient==INVALID_SOCKET)    {     continue;    }    else    {     //如果接收成功我們要把用戶的所有信息存放到鏈表中     if (!AddClientList(sClient,ClientAddr))     {      continue;     }      }   }  } } return 0;} DWORD WINAPI ClientThread(LPVOID lpParam){ //我們將每個用戶的信息以參數的形式傳入到該線程 pNode pTemp = (pNode)lpParam; SOCKET sClient = pTemp->s; //這是通信套接字 WSAEVENT Event = WSACreateEvent(); //該事件是與通信套接字關聯以判斷事件的種類 WSANETWORKEVENTS NetWorkEvent; char szRequest[1024]={0}; //請求報文 char szResponse[1024]={0}; //響應報文 BOOL bKeepAlive = FALSE; //是否持續連接 if(Event == WSA_INVALID_EVENT) {  return -1; } int Ret = WSAEventSelect(sClient, Event, FD_READ | FD_WRITE | FD_CLOSE); //關聯事件和套接字 DWORD dwIndex = 0; while (1) {  dwIndex = WSAWaitForMultipleEvents(1,&Event,FALSE,WSA_INFINITE,FALSE);  dwIndex = dwIndex - WAIT_OBJECT_0;  if (dwIndex==WSA_WAIT_TIMEOUT||dwIndex==WSA_WAIT_FAILED)  {   continue;  }  // 分析什么網絡事件產生  Ret = WSAEnumNetworkEvents(sClient,Event,&NetWorkEvent);  //其他情況  if(!NetWorkEvent.lNetworkEvents)  {   continue;  }  if (NetWorkEvent.lNetworkEvents & FD_READ) //這里很有意思的  {    DWORD NumberOfBytesRecvd;    WSABUF Buffers;    DWORD dwBufferCount = 1;    char szBuffer[MAX_BUFFER];    DWORD Flags = 0;    Buffers.buf = szBuffer;    Buffers.len = MAX_BUFFER;    Ret = WSARecv(sClient,&Buffers,dwBufferCount,&NumberOfBytesRecvd,&Flags,NULL,NULL);    //我們在這里要檢測是否得到的完整請求    memcpy(szRequest,szBuffer,NumberOfBytesRecvd);    if (!IoComplete(szRequest)) //校驗數據包    {     continue;    }    if (!ParseRequest(szRequest, szResponse, bKeepAlive)) //分析數據包    {     //我在這里就進行了簡單的處理     continue;    }    DWORD NumberOfBytesSent = 0;    DWORD dwBytesSent = 0;    //發送響應到客戶端    do    {     Buffers.len = (strlen(szResponse) - dwBytesSent) >= SENDBLOCK ? SENDBLOCK : strlen(szResponse) - dwBytesSent;      Buffers.buf = (char*)((DWORD)szResponse + dwBytesSent);       Ret = WSASend(      sClient,                  &Buffers,                1,               &NumberOfBytesSent,      0,                 0,             NULL);       if(SOCKET_ERROR != Ret)      dwBytesSent += NumberOfBytesSent;    }    while((dwBytesSent < strlen(szResponse)) && SOCKET_ERROR != Ret);   }   if(NetWorkEvent.lNetworkEvents & FD_CLOSE)  {    //在這里我沒有處理,我們要將內存進行釋放否則內存泄露  } } return 0;} bool InitSocket(){ WSADATA wsadata; if (WSAStartup(MAKEWORD(2,2),&wsadata)==0)    //使用Socket前必須調用 參數 作用 返回值 {  return true; } return false;} bool AddClientList(SOCKET s,sockaddr_in addr){ pNode pTemp = (pNode)malloc(sizeof(Node)); HANDLE hThread = NULL; DWORD ThreadID = 0; if (pTemp==NULL) {  printf("No Memory/n");  return false; } else {  pTemp->s = s;  pTemp->Addr = addr;  pTemp->pNext = NULL;  if (pHead==NULL)  {   pHead = pTail = pTemp;  }  else  {   pTail->pNext = pTemp;   pTail = pTail->pNext;  }  //我們要為用戶開辟新的線程  hThread = CreateThread(NULL,0,ClientThread,(LPVOID)pTemp,0,&ThreadID);  if (hThread==NULL)  {   free(pTemp);   return false;  }  if (!AddThreadList(hThread,ThreadID))  {   free(pTemp);   return false;  } } return true;} bool AddThreadList(HANDLE hThread,DWORD ThreadID){ pThread pTemp = (pThread)malloc(sizeof(Thread));  if (pTemp==NULL) {  printf("No Memory/n");   return false; } else {  pTemp->hThread = hThread;  pTemp->ThreadID = ThreadID;  pTemp->pNext = NULL;   if (pHeadThread==NULL)  {   pHeadThread = pTailThread = pTemp;  }   else  {   pTailThread->pNext = pTemp;     pTailThread = pTailThread->pNext;  } } return true;} //校驗數據包bool IoComplete(char* szRequest){ char* pTemp = NULL;   //定義臨時空指針 int nLen = strlen(szRequest); //請求數據包長度 pTemp = szRequest;    pTemp = pTemp+nLen-4; //定位指針 if (strcmp(pTemp,"/r/n/r/n")==0)   //校驗請求頭部行末尾的回車控制符和換行符以及空行 {  return true; } return false;} //分析數據包bool ParseRequest(char* szRequest, char* szResponse, BOOL &bKeepAlive){ char* p = NULL; p = szRequest; int n = 0; char* pTemp = strstr(p," "); //判斷字符串str2是否是str1的子串。如果是,則該函數返回str2在str1中首次出現的地址;否則,返回NULL。 n = pTemp - p;    //指針長度// pTemp = pTemp + n - 1; //將我們的指針下移 //定義一個臨時的緩沖區來存放我們 char szMode[10]={0}; char szFileName[10]={0}; memcpy(szMode,p,n);   //將請求方法拷貝到szMode數組中 if (strcmp(szMode,"GET")==0)  //一定要將Get寫成大寫 {  //獲取文件名  pTemp = strstr(pTemp," ");  pTemp = pTemp + 1;   //只有調試的時候才能發現這里的秘密  memcpy(szFileName,pTemp,1);  if (strcmp(szFileName,"/")==0)  {   strcpy(szFileName,FileName);  }  else  {   return false;  } } else {  return false; } // 分析鏈接類型 pTemp = strstr(szRequest,"/nConnection: Keep-Alive");  //協議版本 n = pTemp - p; if (p>0) {  bKeepAlive = TRUE; } else  //這里的設置是為了Proxy程序的運行 {  bKeepAlive = TRUE; } //定義一個回顯頭 char pResponseHeader[512]={0}; char szStatusCode[20]={0}; char szContentType[20]={0}; strcpy(szStatusCode,"200 OK"); strcpy(szContentType,"text/html"); char szDT[128]; struct tm *newtime; long ltime; time(<ime); newtime = gmtime(<ime); strftime(szDT, 128,"%a, %d %b %Y %H:%M:%S GMT", newtime); //讀取文件 //定義一個文件流指針 FILE* fp = fopen(HtmlDir,"rb"); fpos_t lengthActual = 0; int length = 0; char* BufferTemp = NULL; if (fp!=NULL) {  // 獲得文件大小  fseek(fp, 0, SEEK_END);  fgetpos(fp, &lengthActual);  fseek(fp, 0, SEEK_SET);  //計算出文件的大小后我們進行分配內存  BufferTemp = (char*)malloc(sizeof(char)*((int)lengthActual));  length = fread(BufferTemp,1,(int)lengthActual,fp);  fclose(fp);  // 返回響應  sprintf(pResponseHeader, "HTTP/1.0 %s/r/nDate: %s/r/nServer: %s/r/nAccept-Ranges: bytes/r/nContent-Length: %d/r/nConnection: %s/r/nContent-Type: %s/r/n/r/n",   szStatusCode, szDT, SERVERNAME, length, bKeepAlive ? "Keep-Alive" : "close", szContentType);   //響應報文 } //如果我們的文件沒有找到我們將引導用戶到另外的錯誤頁面 else { } strcpy(szResponse,pResponseHeader); strcat(szResponse,BufferTemp); free(BufferTemp); BufferTemp = NULL; return true;}

以上就是本文的全部內容,希望對大家的學習有所幫助。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
裸体女人亚洲精品一区| 日韩欧美精品在线观看| 中文字幕日韩av电影| 久久影视三级福利片| 亚洲欧美国产一区二区三区| 久久久精品网站| 成人精品视频久久久久| www.久久草.com| 国产精品亚洲综合天堂夜夜| 国产精品久久久久久久久久99| 8090理伦午夜在线电影| 亚洲欧美日韩第一区| 欧美激情国内偷拍| 日本精品免费一区二区三区| 97在线视频国产| 久久精品99无色码中文字幕| 亚洲黄在线观看| 欧美大胆a视频| 日韩欧美国产视频| 一区二区福利视频| 欧美亚洲成人免费| 日韩久久午夜影院| 国产伦精品一区二区三区精品视频| 91精品国产综合久久香蕉| 久久久久成人精品| 91爱视频在线| 亚洲爱爱爱爱爱| 性欧美长视频免费观看不卡| 欧洲精品毛片网站| 国产精品海角社区在线观看| 欧美成人午夜激情视频| 久久成人精品一区二区三区| 成人字幕网zmw| 中文字幕亚洲精品| 伦伦影院午夜日韩欧美限制| 欧美亚洲国产日韩2020| 日韩在线一区二区三区免费视频| 久久精品国产v日韩v亚洲| 久久久久一本一区二区青青蜜月| 精品国产一区二区三区四区在线观看| 欧美成人sm免费视频| 日韩三级成人av网| 久久久久久尹人网香蕉| 国产亚洲欧洲在线| www国产精品com| 91在线观看免费观看| 日产精品久久久一区二区福利| 久久免费视频网站| 国产极品精品在线观看| 国产亚洲欧美另类中文| 91久久久亚洲精品| 国产69精品99久久久久久宅男| 亚洲视频网站在线观看| 日韩中文字幕在线视频| 久久久人成影片一区二区三区观看| 日韩在线欧美在线国产在线| 91tv亚洲精品香蕉国产一区7ujn| 成人亚洲激情网| 久久精品国产久精国产一老狼| 欧美激情一区二区三区在线视频观看| 国产精自产拍久久久久久| 动漫精品一区二区| 欧美一级视频一区二区| 亚洲偷欧美偷国内偷| 亚洲已满18点击进入在线看片| 正在播放亚洲1区| 91沈先生在线观看| 97香蕉久久超级碰碰高清版| 亚洲免费成人av电影| 狠狠色狠狠色综合日日五| 欧美亚州一区二区三区| 欧美成年人视频| 91av在线网站| 91精品国产乱码久久久久久久久| 97欧美精品一区二区三区| 日韩欧美国产免费播放| 欧美电影在线观看高清| 7777精品视频| 欧美黄色成人网| 麻豆精品精华液| 亚洲国产精品久久91精品| 亚洲高清久久久久久| 色777狠狠综合秋免鲁丝| 久久97久久97精品免视看| 国产mv免费观看入口亚洲| 久久久久久久久亚洲| 4p变态网欧美系列| 一个人看的www久久| 色婷婷综合成人| 97精品国产97久久久久久| 日韩黄色高清视频| 亚洲天天在线日亚洲洲精| 日韩在线不卡视频| 啪一啪鲁一鲁2019在线视频| 亚洲区免费影片| 国产精品久久激情| 热re91久久精品国99热蜜臀| 91av视频在线免费观看| 7m第一福利500精品视频| 欧美激情在线观看视频| 情事1991在线| 亚洲一区美女视频在线观看免费| 亚洲视频在线看| 日韩电影免费在线观看| 精品香蕉一区二区三区| 亚洲摸下面视频| 韩国三级电影久久久久久| 日本高清+成人网在线观看| 26uuu国产精品视频| 欧美精品手机在线| 国产精品27p| 久久免费福利视频| 亚洲bt天天射| 国产小视频91| 久久久久免费精品国产| 国产精品一二三视频| 欧美高清自拍一区| 91精品成人久久| 亚洲一品av免费观看| 久久久久久久久爱| 国产一区二区视频在线观看| 日韩美女视频免费在线观看| 国产日本欧美一区| 2021国产精品视频| 搡老女人一区二区三区视频tv| 久久精品国产电影| 91精品中文在线| 成人a视频在线观看| 国产精品入口福利| 亚洲大胆人体在线| 亚洲一区中文字幕在线观看| 97精品国产97久久久久久春色| 97视频在线观看亚洲| 亚洲精品久久久久国产| 国产精品精品久久久久久| 欧美成人免费播放| 性欧美长视频免费观看不卡| 欧洲日本亚洲国产区| 久久久www成人免费精品| 一区二区福利视频| 国产亚洲精品美女久久久久| 欧美国产日本高清在线| 欧美黑人巨大精品一区二区| 日韩久久免费电影| 日本一欧美一欧美一亚洲视频| 伊人久久五月天| 日韩av在线精品| 国产精品在线看| 日韩精品在线观看一区二区| 欧美大学生性色视频| 国产精品久久久久久av福利软件| 欧美日韩亚洲视频| 日韩在线一区二区三区免费视频| 国产主播欧美精品| 久久久黄色av| 国产亚洲欧美日韩精品| 92看片淫黄大片看国产片| 日韩免费不卡av| 亚洲欧美在线免费观看| 国产丝袜精品视频| 中文字幕视频在线免费欧美日韩综合在线看| 中文字幕国内精品| 亚洲天堂av在线免费观看| 国产亚洲一区二区精品|