simpleHttp服务器类

simpleHttp服务器类
#pragma once

#include 
< WinSock2.h >


class  CHpServer
{
public:
    CHpServer(
void);
    
virtual ~CHpServer(void);

    BOOL StartSever(CString RootDir, u_short port);
    
void StopServer();

protected:
    BOOL RecvRequest(SOCKET sk, HANDLE hExit, PCHAR pBuf, DWORD bufSize);
    
int ParseRequest(PCHAR lpBuf, CString &fileName);
    
void SendFile(SOCKET sk, HANDLE hExit, CString filePath);
    BOOL SendBuffer(SOCKET sk, HANDLE hExit, PCHAR pBuf, DWORD bufSize);


    
static DWORD WINAPI ListenThread(PVOID lParam);
    
static DWORD WINAPI ClientThread(PVOID lParam);

private:
    SOCKET m_lsSocket;
    CString m_RootDir;
}
;


typedef 
struct  stg_Req
{
    SOCKET skClient;
    HANDLE hExitEvent;
    CString rootDir;
    CHpServer
* pThis;
}
REQUEST,  * LPReq;


  1 #include  " StdAfx.h "
  2 #include  " HpServer.h "
  3
  4 CHpServer::CHpServer( void )
  5 {
  6    WSADATA wsaData;
  7    WSAStartup(MAKEWORD(2,2), &wsaData);
  8
  9    m_lsSocket = INVALID_SOCKET;
 10}

 11
 12 CHpServer:: ~ CHpServer( void )
 13 {
 14    WSACleanup();
 15}

 16
 17 BOOL CHpServer::StartSever(CString RootDir, u_short port)
 18 {
 19    if (strcmp(RootDir, _T("")) == 0)
 20        return FALSE;
 21
 22    m_RootDir = RootDir;
 23    m_lsSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
 24    SOCKADDR_IN sk_Addr;
 25
 26    sk_Addr.sin_family = AF_INET;
 27    sk_Addr.sin_port = htons(port);
 28    sk_Addr.sin_addr.s_addr = ADDR_ANY;
 29
 30    if (bind(m_lsSocket, (LPSOCKADDR)&sk_Addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
 31    {
 32        closesocket(m_lsSocket);
 33        return FALSE;
 34    }

 35    if (listen(m_lsSocket, 10== SOCKET_ERROR)
 36    {
 37        closesocket(m_lsSocket);
 38        return FALSE;
 39    }

 40    
 41    DWORD dwThreadID;
 42    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ListenThread, this, NULL, &dwThreadID);
 43    if (hThread == INVALID_HANDLE_VALUE)
 44        return FALSE;
 45    CloseHandle(hThread);
 46
 47    return TRUE;
 48}

 49
 50 void  CHpServer::StopServer()
 51 {
 52    if (m_lsSocket != INVALID_SOCKET)
 53    {
 54        closesocket(m_lsSocket);
 55        m_lsSocket = INVALID_SOCKET;
 56    }

 57}

 58
 59 DWORD WINAPI CHpServer::ListenThread(PVOID lParam)
 60 {
 61    CHpServer* pThis = (CHpServer*)lParam;
 62    HANDLE hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 63
 64    while (TRUE)
 65    {
 66        SOCKADDR_IN sk_Addr;
 67        int nSize = sizeof(sk_Addr);
 68        SOCKET skClient = accept(pThis->m_lsSocket, (PSOCKADDR)&sk_Addr, &nSize);
 69
 70        if (skClient == INVALID_SOCKET)
 71            break;
 72
 73        LPReq lpReq = new REQUEST;
 74        lpReq->skClient = skClient;
 75        lpReq->hExitEvent = hExitEvent;
 76        lpReq->rootDir = pThis->m_RootDir;
 77
 78        DWORD dwThreadID;
 79        HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ClientThread, lpReq, NULL, &dwThreadID);
 80        if (hThread == INVALID_HANDLE_VALUE)
 81        {
 82            closesocket(skClient);
 83            delete lpReq;
 84            continue;
 85        }

 86        CloseHandle(hThread);
 87    }

 88    SetEvent(hExitEvent);
 89    Sleep(1000);    //等待服务线程退出
 90    CloseHandle(hExitEvent);
 91
 92    return 1;
 93}

 94
 95 DWORD WINAPI CHpServer::ClientThread(PVOID lParam)
 96 {
 97    LPReq lpReq = (LPReq)lParam;
 98    
 99    CHAR buf[1024];
100
101    if (!lpReq->pThis->RecvRequest(lpReq->skClient, lpReq->hExitEvent, buf, 1024))
102    {
103        closesocket(lpReq->skClient);
104        delete lpReq;
105        return 1;
106    }

107    CString filePath = lpReq->rootDir;
108
109    if (!lpReq->pThis->ParseRequest(buf, filePath))
110    {
111        closesocket(lpReq->skClient);
112        delete lpReq;
113        return 1;
114    }

115    
116    lpReq->pThis->SendFile(lpReq->skClient, lpReq->hExitEvent, filePath);
117
118    closesocket(lpReq->skClient);
119    delete lpReq;
120    return 1;
121}

122
123
124 BOOL CHpServer::RecvRequest(SOCKET sk, HANDLE hExit, PCHAR pBuf, DWORD bufSize)
125 {
126    memset(pBuf, 0, bufSize);
127
128    WSABUF wsaBuf;
129    WSAOVERLAPPED wsaOver;
130
131    wsaBuf.buf = pBuf;
132    wsaBuf.len = bufSize;
133    wsaOver.hEvent = WSACreateEvent();
134    
135    DWORD dwRecvSize, dwFlags = 0;
136    int nRet = WSARecv(sk, &wsaBuf, 1&dwRecvSize, &dwFlags, &wsaOver, NULL);
137    
138    if (nRet != 0 && WSAGetLastError() != WSA_IO_PENDING)
139    {
140        CloseHandle(wsaOver.hEvent);
141        return FALSE;
142    }

143
144    if (nRet != 0)
145    {
146        HANDLE hEvents[2= {wsaOver.hEvent, hExit};
147
148        if ( WaitForMultipleObjects(2, hEvents, FALSE, INFINITE) != 0)
149        {
150            CloseHandle(wsaOver.hEvent);
151            return FALSE;
152        }

153
154        if (!WSAGetOverlappedResult(sk,
155                &wsaOver,
156                &dwRecvSize,
157                FALSE,
158                &dwFlags))
159        {
160            CloseHandle(wsaOver.hEvent);
161            return FALSE;
162        }

163    }

164
165    CloseHandle(wsaOver.hEvent);
166    return TRUE;
167}

168
169 int  CHpServer::ParseRequest(PCHAR lpBuf, CString  & filePath)
170 {
171    PCHAR cpNtToken;
172    PCHAR cpToken = strtok_s(lpBuf, _T(" \n"), &cpNtToken);
173
174    if (strcmp(cpToken, _T("GET")) != 0)
175        return 0;
176
177    cpToken = strtok_s(NULL, _T(" \n"), &cpNtToken);
178    if (cpToken == NULL)
179        return 0;
180    
181    filePath.Format(_T("%s%s"),filePath, cpToken);
182
183    return 1;
184}

185
186
187 void  CHpServer::SendFile(SOCKET sk, HANDLE hExit, CString fileName)
188 {
189    HANDLE hFile = CreateFile(fileName,
190        GENERIC_READ,
191        FILE_SHARE_READ,
192        NULL,
193        OPEN_EXISTING,
194        FILE_ATTRIBUTE_NORMAL,
195        NULL);
196
197    if (hFile == INVALID_HANDLE_VALUE)
198        return;
199
200    DWORD dwSize = GetFileSize(hFile,NULL);
201    TCHAR pResponseHeader[1024];
202    sprintf_s(pResponseHeader, 1024,
203        _T("HTTP/1.1 200 OK\r\nAccept-Ranges: bytes\r\nContent-Length: "\
204        "%d\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\n\r\n"),
205        dwSize);
206    SendBuffer(sk,hExit,pResponseHeader,strlen(pResponseHeader));
207
208    static CHAR buf[1024];
209    while (WaitForSingleObject(hExit, 0== WAIT_TIMEOUT)
210    {
211        DWORD dwSize;
212        if (!ReadFile(hFile, buf, 1024&dwSize, NULL) || dwSize == 0)
213            break;
214
215        if (!SendBuffer(sk, hExit, buf, dwSize))
216            break;
217    }

218
219    CloseHandle(hFile);
220}

221
222 BOOL CHpServer::SendBuffer(SOCKET sk, HANDLE hExit, PCHAR pBuf, DWORD bufSize)
223 {
224    WSABUF wsaBuf;
225    WSAOVERLAPPED wsaOver;
226
227    wsaBuf.buf = pBuf;
228    wsaBuf.len = bufSize;
229    wsaOver.hEvent = WSACreateEvent();
230    
231    DWORD dwRecv, dwFlags;
232    int nRet = WSASend(sk, &wsaBuf, 1&dwRecv, 0&wsaOver, NULL); 
233    if (nRet != 0 && WSAGetLastError() != WSA_IO_PENDING)
234        return FALSE;
235    
236    if (nRet != 0)
237    {
238        HANDLE hEvents[2= {wsaOver.hEvent, hExit};
239
240        if (WaitForMultipleObjects(2, hEvents, FALSE, INFINITE) != 0)
241        {
242            CloseHandle(wsaOver.hEvent);
243            return FALSE;
244        }

245
246        if (!WSAGetOverlappedResult(sk, &wsaOver, &dwRecv, FALSE, &dwFlags))
247        {
248            CloseHandle(wsaOver.hEvent);
249            return FALSE;
250        }

251    }

252    
253    CloseHandle(wsaOver.hEvent);
254    return TRUE;
255}

256
257

你可能感兴趣的:(simpleHttp服务器类)