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;
#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
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