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(<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
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;
}
以上が本文のすべての内容で、みんなの学習に役立つことを望みます.