C++簡単なHTTPサーバーを実現

11196 ワード

この例では、C++実装HTTPサーバに関するコードについて説明します.

#include 
#include 
#include 
#include 
#include 
#include 
 
#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
"); 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
"); 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
"); return -1; } // listen(sListen,5); // WSAEVENT Event = WSACreateEvent(); if (Event==WSA_INVALID_EVENT) { printf("Create WSAEVENT Error
"); 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
"); 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
"); 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
\r
")==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,"
Connection: 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(&ltime); newtime = gmtime(&ltime); 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
Date: %s\r
Server: %s\r
Accept-Ranges: bytes\r
Content-Length: %d\r
Connection: %s\r
Content-Type: %s\r
\r
", szStatusCode, szDT, SERVERNAME, length, bKeepAlive ? "Keep-Alive" : "close", szContentType); // } // else { } strcpy(szResponse,pResponseHeader); strcat(szResponse,BufferTemp); free(BufferTemp); BufferTemp = NULL; return true; }

以上が本文のすべての内容で、みんなの学習に役立つことを望みます.