• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

zhaozongzhe

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

node.js的单线程异步模式的在Windows下的IOCP实现

先看看的node.js的比较有趣特征:
(摘自http://baike.baidu.com/view/3974030.htm)

“Node采用了一个称为“事件循环(event loop)”的架构,使得编写可扩展性高的服务器变得既容易又安全。提高服务器性能的技巧有多种多样。Node选择了一种既能提高性能,又能减低开发复杂度的架构。这是一个非常重要的特性。并发编程通常很复杂且布满地雷。Node绕过了这些,但仍提供很好的性能。

Node采用一系列“非阻塞”库来支持事件循环的方式。本质上就是为文件系统、数据库之类的资源提供接口。向文件系统发送一个请求时,无需等待硬盘(寻址并检索文件),硬盘准备好的时候非阻塞接口会通知Node。”


查看Node的代码,可以看到它使用一个单一主线程进行工作(libuv,在Windows下是IOCP,Linux下是epoll等等),将其它费时的操作比如文件IO等通过额外的线程库(libeio/libev)来实现。

以下是纯粹Windows下的服务程序的开发实例,里是一个相对简单的实现。

View Code
  1 #include <winsock2.h> 
  2 #include <windows.h> 
  3 #include <mswsock.h> 
  4 #include <stdio.h> 
  5 #include <stdlib.h> 
  6 #include <malloc.h> 
  7 #include <time.h> 
  8 #include <process.h>
  9 
 10 #define TCP_TYPE_LISTEN         1  // 监听 
 11 #define TCP_TYPE_ACCEPT         2 
 12 #define TCP_TYPE_IN             3  // 接受的连接 
 13 #define TCP_TYPE_OUT            4  // 连接到外部服务器
 14 
 15 #define TCP_EV_ACCEPT           1 
 16 #define TCP_EV_CONNECT          2 
 17 #define TCP_EV_CLOSE            3 
 18 #define TCP_EV_SEND             4  // data sent 
 19 #define TCP_EV_RECEIVE          5  // if returns -1, the sock will be CLOSED 
 20 #define TCP_EV_CUSTOM           6  // custom event 
 21 #define TCP_EV_TIMER            7  // abount 100ms
 22 
 23 // 事件回调函数 
 24 // TCP_EV_RECEIVE:,msgData和msgLen为收到的数据和数据大小 
 25 // TCP_EV_CUSTOM: msgData为传入的key 
 26 typedef int (CALLBACK TCPSOCKETEVENTPROC)(int sockIdx, int msgCode, UCHAR *msgData, int msgLen);
 27 
 28 BOOL tcp_startup(int maxSockets, TCPSOCKETEVENTPROC *lpfnEventProc); 
 29 void tcp_cleanup();
 30 
 31 int tcp_listen(const char *ip, u_short port, TCPSOCKETEVENTPROC *lpfnEventProc); 
 32 int tcp_connect(const char *ip, u_short port, TCPSOCKETEVENTPROC *lpfnEventProc); 
 33 BOOL tcp_send(int sockIdx, const void *data1, int dataLen1, const void *data2, int dataLen2);
 34 
 35 void tcp_close(int sockIdx);
 36 
 37 void tcp_pause(int sockIdx); 
 38 void tcp_resume(int sockIdx);
 39 
 40 void tcp_setUserData(int sockIdx, void *lpUserData); 
 41 void *tcp_getUserData(int sockIdx);
 42 
 43 BOOL tcp_getSendStat(int sockIdx, int *sendingSize, int *bufferedSize); 
 44 void tcp_setExpectPackLen(int sockIdx, int packLen);
 45 
 46 void tcp_postEvent(void *key);
 47 
 48 BOOL tcp_getInfo(int sockIdx, struct tcp_info *tsi);
 49 
 50 struct tcp_info 
 51 { 
 52     SOCKET sock; 
 53     LONG type; 
 54     LONG connecting; 
 55     LONG sending; 
 56     LONG paused; 
 57     LONG closing; 
 58     struct 
 59     { 
 60         char ip[20]; 
 61         u_short port; 
 62     } peerAddr, hostAddr; 
 63     TCPSOCKETEVENTPROC *lpfnEventProc; 
 64     LPVOID lpUserData;
 65 
 66     int sockIdxListen; 
 67     time_t lastReceiveTime; 
 68     time_t lastSendTime; 
 69     time_t acceptTime; 
 70     time_t connectTime; 
 71 };
 72 
 73 
 74 struct tcp_buf 
 75 { 
 76     int dlen; 
 77     int alen; 
 78     UCHAR *data; 
 79 };
 80 
 81 static __inline void buf_free(struct tcp_buf *bf) 
 82 { 
 83     if (bf->data != NULL) 
 84         free(bf->data); 
 85     bf->dlen = 0; 
 86     bf->alen = 0; 
 87     bf->data = NULL; 
 88 }
 89 
 90 static __inline void buf_swap(struct tcp_buf *bf1, struct tcp_buf *bf2) 
 91 { 
 92     struct tcp_buf bf;
 93 
 94     bf = *bf1; 
 95     *bf1 = *bf2; 
 96     *bf2 = bf; 
 97 }
 98 
 99 static BOOL buf_alloc(struct tcp_buf *bf, int alloc) 
100 { 
101     if (bf->alen < alloc + 1) 
102     { 
103         const int BLOCK_SIZE = 1024; 
104         int newAlloc; 
105         UCHAR *newBuff;
106 
107         if (alloc < BLOCK_SIZE) 
108             newAlloc = BLOCK_SIZE; 
109         else 
110             newAlloc = (alloc / BLOCK_SIZE + 1) * BLOCK_SIZE;
111 
112         newBuff = (UCHAR *)malloc(newAlloc); 
113         if (newBuff == NULL) return FALSE; 
114         if (bf->data) 
115         { 
116             if (bf->dlen) 
117                 memcpy(newBuff, bf->data, bf->dlen); 
118             free(bf->data); 
119         } 
120         bf->data = newBuff; 
121         bf->alen = newAlloc; 
122     } 
123     return TRUE; 
124 }
125 
126 static BOOL buf_append(struct tcp_buf *bf, const void *data, int dlen) 
127 { 
128     if (!buf_alloc(bf, bf->dlen + dlen + 1)) 
129         return FALSE;
130 
131     memcpy(bf->data + bf->dlen, data, dlen); 
132     bf->dlen += dlen; 
133     return TRUE; 
134 }
135 
136 static void buf_erase(struct tcp_buf *bf, int erase_pos, int erase_len) 
137 { 
138     if (erase_pos >= 0 && 
139         erase_pos < bf->dlen && 
140         (erase_pos + erase_len) <= bf->dlen) 
141     { 
142         if ((erase_pos + erase_len) < bf->dlen) 
143             memmove(bf->data + erase_pos, 
144                 bf->data + erase_pos + erase_len, 
145                 bf->dlen - erase_pos - erase_len); 
146         bf->dlen -= erase_len; 
147     } 
148 }
149 
150 // ----------------------------------------------------------------------- 
151 // socket status 
152 #define STAT_CONNECTING             0x01 
153 #define STAT_PAUSED                 0x02 
154 #define STAT_CLOSING                0x04 
155 #define STAT_RECEIVING              0x10 
156 #define STAT_SENDING                0x20
157 
158 struct tcp_socket 
159 { 
160     UINT64 id;              // opt future 
161     SOCKET sock; 
162     LONG type; 
163     LONG stat; 
164     struct sockaddr_in addr; 
165     TCPSOCKETEVENTPROC *lpfnEventProc; 
166     PVOID lpUserData; 
167     LONG expectPackLen;
168 
169     OVERLAPPED ovlpSend; 
170     OVERLAPPED ovlpReceive; 
171     OVERLAPPED ovlpConnect; 
172     OVERLAPPED ovlpClose;
173 
174     struct tcp_buf bufSending; 
175     struct tcp_buf bufToSend; 
176     struct tcp_buf bufRecv; 
177     int sockIdxListen; 
178     int sockIdxAccept; 
179     time_t lastReceiveTime; 
180     time_t lastSendTime; 
181     time_t acceptTime; 
182     time_t connectTime; 
183 };
184 
185 static HANDLE g_completionPort = NULL; 
186 static OVERLAPPED g_ovlpExit = { 0 };
187 
188 static struct tcp_socket **g_sockets = NULL; 
189 static int g_maxSockets = 0; 
190 static TCPSOCKETEVENTPROC *g_lpfnEventProc = NULL; 
191 static HANDLE g_thread = NULL;
192 
193 static LPFN_CONNECTEX g_lpfnConnectEx = NULL; 
194 static LPFN_ACCEPTEX g_lpfnAcceptEx = NULL; 
195 static LPFN_DISCONNECTEX g_lpfnDisconnectEx = NULL;
196 
197 
198 void tcp_setUserData(int sockIdx, void *lpUserData) 
199 { 
200     if (sockIdx >= 0 && sockIdx < g_maxSockets && g_sockets[sockIdx]) 
201         g_sockets[sockIdx]->lpUserData = lpUserData; 
202 }
203 
204 void *tcp_getUserData(int sockIdx) 
205 { 
206     return ((sockIdx >= 0 && sockIdx < g_maxSockets && g_sockets[sockIdx]) 
207         ? g_sockets[sockIdx]->lpUserData : NULL); 
208 }
209 
210 void tcp_setExpectPackLen(int sockIdx, int packLen) 
211 { 
212     if (sockIdx >= 0 && sockIdx < g_maxSockets && g_sockets[sockIdx]) 
213         g_sockets[sockIdx]->expectPackLen = packLen; 
214 }
215 
216 BOOL tcp_getSendStat(int sockIdx, int *sendingSize, int *bufferedSize) 
217 { 
218     *sendingSize = 0; 
219     *bufferedSize = 0;
220 
221     if (sockIdx >= 0 && sockIdx < g_maxSockets && g_sockets[sockIdx]) 
222     { 
223         if (g_sockets[sockIdx]->stat & STAT_SENDING) 
224             *sendingSize = g_sockets[sockIdx]->bufSending.dlen; 
225         *bufferedSize = g_sockets[sockIdx]->bufToSend.dlen; 
226         return TRUE; 
227     }
228 
229     return FALSE; 
230 }
231 
232 // called from outside threads 
233 void tcp_postEvent(void *key) 
234 { 
235     PostQueuedCompletionStatus(g_completionPort, 0, (ULONG_PTR)(-11), (LPOVERLAPPED)key); 
236 }
237 
238 BOOL tcp_getInfo(int sockIdx, struct tcp_info *tsi) 
239 { 
240     struct sockaddr_in addr; 
241     int addrLen = sizeof(tsi->hostAddr);
242 
243     memset(tsi, 0, sizeof(*tsi)); 
244     tsi->sock = INVALID_SOCKET; 
245     tsi->sockIdxListen = -1;
246 
247     if (sockIdx < 0 || sockIdx >= g_maxSockets || !g_sockets[sockIdx]) 
248         return FALSE;
249 
250     tsi->sock = g_sockets[sockIdx]->sock; 
251     tsi->type = g_sockets[sockIdx]->type; 
252     tsi->connecting = g_sockets[sockIdx]->stat & STAT_CONNECTING; 
253     tsi->sending = g_sockets[sockIdx]->stat & STAT_SENDING; 
254     tsi->paused = g_sockets[sockIdx]->stat & STAT_PAUSED; 
255     tsi->closing = g_sockets[sockIdx]->stat & STAT_CLOSING; 
256     getpeername(g_sockets[sockIdx]->sock, (struct sockaddr *)&addr, &addrLen); 
257     strcpy_s(tsi->peerAddr.ip, 20, inet_ntoa(addr.sin_addr)); 
258     tsi->peerAddr.port = ntohs(addr.sin_port); 
259     getsockname(g_sockets[sockIdx]->sock, (struct sockaddr *)&addr, &addrLen); 
260     strcpy_s(tsi->hostAddr.ip, 20, inet_ntoa(addr.sin_addr)); 
261     tsi->hostAddr.port = ntohs(addr.sin_port); 
262     tsi->lpfnEventProc = g_sockets[sockIdx]->lpfnEventProc; 
263     tsi->lpUserData = g_sockets[sockIdx]->lpUserData; 
264     tsi->sockIdxListen = g_sockets[sockIdx]->sockIdxListen; 
265     tsi->lastReceiveTime = g_sockets[sockIdx]->lastReceiveTime; 
266     tsi->lastSendTime = g_sockets[sockIdx]->lastSendTime; 
267     tsi->acceptTime = g_sockets[sockIdx]->acceptTime; 
268     tsi->connectTime = g_sockets[sockIdx]->connectTime;
269 
270     return TRUE; 
271 }
272 
273 static void tcp_clean(int sockIdx) 
274 { 
275     g_sockets[sockIdx]->type = 0; 
276     g_sockets[sockIdx]->stat = 0; 
277     memset(&g_sockets[sockIdx]->addr, 0, sizeof(g_sockets[sockIdx]->addr)); 
278     g_sockets[sockIdx]->lpUserData = NULL;
279 
280     memset(&g_sockets[sockIdx]->ovlpSend, 0, sizeof(OVERLAPPED)); 
281     memset(&g_sockets[sockIdx]->ovlpReceive, 0, sizeof(OVERLAPPED)); 
282     memset(&g_sockets[sockIdx]->ovlpConnect, 0, sizeof(OVERLAPPED)); 
283     memset(&g_sockets[sockIdx]->ovlpClose, 0, sizeof(OVERLAPPED)); 
284     g_sockets[sockIdx]->bufSending.dlen = 0; 
285     g_sockets[sockIdx]->bufToSend.dlen = 0; 
286     g_sockets[sockIdx]->bufRecv.dlen = 0; 
287     g_sockets[sockIdx]->sockIdxListen = -1; 
288     g_sockets[sockIdx]->sockIdxAccept = -1; 
289     g_sockets[sockIdx]->lastReceiveTime = 0; 
290     g_sockets[sockIdx]->lastSendTime = 0; 
291     g_sockets[sockIdx]->acceptTime = 0; 
292     g_sockets[sockIdx]->connectTime = 0; 
293 }
294 
295 static int tcp_new(int type) 
296 { 
297     int i, sockIdx;
298 
299     for (i=0, sockIdx=-1; i<g_maxSockets; i++) 
300     { 
301         if (!g_sockets[i] || !g_sockets[i]->type) 
302         { 
303             sockIdx = i; 
304             break; 
305         } 
306     }
307 
308     if (sockIdx < 0) return -1;
309 
310     if (!g_sockets[sockIdx]) 
311     { 
312         g_sockets[sockIdx] = (struct tcp_socket *)malloc(sizeof(struct tcp_socket)); 
313         if (!g_sockets[sockIdx]) return -1; 
314         memset(g_sockets[sockIdx], 0, sizeof(struct tcp_socket)); 
315         g_sockets[sockIdx]->sock = INVALID_SOCKET; 
316     }
317 
318     tcp_clean(sockIdx);
319 
320     g_sockets[sockIdx]->type = type; 
321     g_sockets[sockIdx]->lpUserData = NULL;
322 
323     return sockIdx; 
324 }
325 
326 static void tcp_release(int sockIdx, BOOL notify) 
327 { 
328     if (sockIdx < 0 || sockIdx >= g_maxSockets || 
329         !g_sockets[sockIdx] || !g_sockets[sockIdx]->type) 
330         return;
331 
332     if (g_sockets[sockIdx]->sock != INVALID_SOCKET) 
333     { 
334         CancelIo((HANDLE)g_sockets[sockIdx]->sock); 
335         closesocket(g_sockets[sockIdx]->sock); 
336         g_sockets[sockIdx]->sock = INVALID_SOCKET; 
337     }
338 
339     if (notify && g_sockets[sockIdx]->type && 
340         g_sockets[sockIdx]->type != TCP_TYPE_ACCEPT && 
341         g_sockets[sockIdx]->lpfnEventProc) 
342         g_sockets[sockIdx]->lpfnEventProc(sockIdx, TCP_EV_CLOSE, NULL, 0);
343 
344     tcp_clean(sockIdx); 
345 }
346 
347 void tcp_close(int sockIdx) 
348 { 
349     if (sockIdx < 0 || sockIdx >= g_maxSockets || 
350         !g_sockets[sockIdx] || !g_sockets[sockIdx]->type) 
351         return;
352 
353     g_sockets[sockIdx]->stat |= STAT_CLOSING;
354 
355     PostQueuedCompletionStatus(g_completionPort, 0, sockIdx, (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpClose); 
356 }
357 
358 BOOL tcp_send(int sockIdx, 
359               const void *data1, int dataLen1, 
360               const void *data2, int dataLen2) 
361 { 
362     if (sockIdx < 0 || sockIdx >= g_maxSockets || 
363         !g_sockets[sockIdx] || 
364         (g_sockets[sockIdx]->type != TCP_TYPE_IN && 
365         g_sockets[sockIdx]->type != TCP_TYPE_OUT) || 
366         g_sockets[sockIdx]->sock == INVALID_SOCKET || 
367         g_sockets[sockIdx]->stat & 0x0F) 
368         return FALSE;
369 
370     if (g_sockets[sockIdx]->stat & STAT_SENDING) 
371     { 
372         if (g_sockets[sockIdx]->bufToSend.dlen > 10*1024*1024) return FALSE;
373 
374         if (data1 && dataLen1) 
375             buf_append(&g_sockets[sockIdx]->bufToSend, data1, dataLen1); 
376         if (data2 && dataLen2) 
377             buf_append(&g_sockets[sockIdx]->bufToSend, data2, dataLen2);
378 
379         return TRUE; 
380     }
381 
382     if (data1 && dataLen1) 
383         buf_append(&g_sockets[sockIdx]->bufSending, data1, dataLen1); 
384     if (data2 && dataLen2) 
385         buf_append(&g_sockets[sockIdx]->bufSending, data2, dataLen2);
386 
387     if (!g_sockets[sockIdx]->bufSending.dlen) return TRUE;
388 
389     g_sockets[sockIdx]->stat |= STAT_SENDING;
390 
391     if (!WriteFile( 
392         (HANDLE)g_sockets[sockIdx]->sock, 
393         g_sockets[sockIdx]->bufSending.data, 
394         g_sockets[sockIdx]->bufSending.dlen, 
395         NULL, 
396         (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpSend)) 
397     { 
398         DWORD lastErr = GetLastError(); 
399         if (lastErr != ERROR_IO_PENDING) 
400         { 
401             PostQueuedCompletionStatus(g_completionPort, 0, sockIdx, 
402                 (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpClose); 
403             return FALSE; 
404         } 
405     }
406 
407     return TRUE; 
408 }
409 
410 static void tcp_doReceive(int sockIdx) 
411 { 
412     int bytesToRead;
413 
414     if (g_sockets[sockIdx]->expectPackLen > 0) 
415     { 
416         bytesToRead = max(128, g_sockets[sockIdx]->expectPackLen - g_sockets[sockIdx]->bufRecv.dlen); 
417         buf_alloc(&g_sockets[sockIdx]->bufRecv, g_sockets[sockIdx]->bufRecv.dlen + bytesToRead + 128); 
418         g_sockets[sockIdx]->expectPackLen = 0; 
419     } 
420     else 
421     { 
422         bytesToRead = 1600; 
423         buf_alloc(&g_sockets[sockIdx]->bufRecv, g_sockets[sockIdx]->bufRecv.dlen + bytesToRead); 
424     }
425 
426     g_sockets[sockIdx]->stat |= STAT_RECEIVING;
427 
428     if (!ReadFile((HANDLE)g_sockets[sockIdx]->sock, 
429         g_sockets[sockIdx]->bufRecv.data + g_sockets[sockIdx]->bufRecv.dlen, 
430         bytesToRead, NULL, (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpReceive)) 
431     { 
432         DWORD lastErr = GetLastError(); 
433         if (lastErr != ERROR_IO_PENDING) 
434         { 
435             PostQueuedCompletionStatus(g_completionPort, 0, sockIdx, 
436                 (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpClose); 
437         } 
438     } 
439 }
440 
441 void tcp_pause(int sockIdx) 
442 { 
443     if (sockIdx < 0 || sockIdx >= g_maxSockets || !g_sockets[sockIdx]) 
444         return;
445 
446     g_sockets[sockIdx]->stat |= STAT_PAUSED; 
447 }
448 
449 void tcp_resume(int sockIdx) 
450 { 
451     if (sockIdx < 0 || sockIdx >= g_maxSockets || !g_sockets[sockIdx]) 
452         return;
453 
454     g_sockets[sockIdx]->stat &= ~STAT_PAUSED;
455 
456     if (!(g_sockets[sockIdx]->stat & STAT_RECEIVING)) 
457         tcp_doReceive(sockIdx); 
458 }
459 
460 static int tcp_accept(int sockIdxListen) 
461 { 
462     SOCKET newSocket; 
463     int sockIdx;
464 
465     newSocket = socket(AF_INET, SOCK_STREAM, 0); 
466     if (newSocket == INVALID_SOCKET) return -1;
467 
468     sockIdx = tcp_new(TCP_TYPE_ACCEPT); 
469     if (sockIdx < 0) 
470     { 
471         closesocket(newSocket); 
472         return -1; 
473     }
474 
475     g_sockets[sockIdx]->sock = newSocket; 
476     g_sockets[sockIdx]->sockIdxListen = sockIdxListen; 
477     g_sockets[sockIdx]->lpfnEventProc = g_sockets[sockIdxListen]->lpfnEventProc;
478 
479     g_sockets[sockIdxListen]->sockIdxAccept = sockIdx; 
480     buf_alloc(&g_sockets[sockIdxListen]->bufRecv, 512); 
481     if (!g_lpfnAcceptEx( 
482         g_sockets[sockIdxListen]->sock, g_sockets[sockIdx]->sock, 
483         g_sockets[sockIdxListen]->bufRecv.data, 0, 
484         sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16, 
485         NULL, (LPOVERLAPPED)&g_sockets[sockIdxListen]->ovlpReceive)) 
486     { 
487         DWORD lastErr = WSAGetLastError(); 
488         if (lastErr != ERROR_IO_PENDING) 
489         { 
490             PostQueuedCompletionStatus(g_completionPort, 0, sockIdx, 
491                 (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpClose); 
492             g_sockets[sockIdxListen]->stat |= STAT_CLOSING; // no notify 
493             PostQueuedCompletionStatus(g_completionPort, 0, sockIdxListen, 
494                 (LPOVERLAPPED)&g_sockets[sockIdxListen]->ovlpClose); 
495             return -1; 
496         } 
497     }
498 
499     return sockIdx; 
500 } 
501 
502 int tcp_listen(const char *ip, u_short port, TCPSOCKETEVENTPROC *lpfnEventProc) 
503 { 
504     SOCKET listenSocket; 
505     struct sockaddr_in addr; 
506     int sockIdx;
507 
508     if (!g_maxSockets || !g_sockets) return -1;
509 
510     if (port < 80 || port >= 65535) return -1;
511 
512     listenSocket = socket(AF_INET, SOCK_STREAM, 0); 
513     if (listenSocket == INVALID_SOCKET) return -1;
514 
515     memset(&addr, 0, sizeof(addr)); 
516     addr.sin_family = AF_INET; 
517     addr.sin_addr.s_addr = inet_addr(ip); 
518     if (addr.sin_addr.s_addr == INADDR_NONE) 
519         addr.sin_addr.s_addr = INADDR_ANY; 
520     addr.sin_port = htons(port); 
521     if (bind(listenSocket, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) 
522     { 
523         closesocket(listenSocket); 
524         return -1; 
525     } 
526     if (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) 
527     { 
528         closesocket(listenSocket); 
529         return -1; 
530     }
531 
532     sockIdx = tcp_new(TCP_TYPE_LISTEN); 
533     if (sockIdx < 0) 
534     { 
535         closesocket(listenSocket); 
536         return -1; 
537     }
538 
539     g_sockets[sockIdx]->sock = listenSocket; 
540     g_sockets[sockIdx]->lpfnEventProc = (lpfnEventProc ? lpfnEventProc : g_lpfnEventProc);
541 
542     CreateIoCompletionPort((HANDLE)g_sockets[sockIdx]->sock, g_completionPort, (ULONG_PTR)sockIdx, 0); 
543     tcp_accept(sockIdx);
544 
545     return sockIdx; 
546 }
547 
548 int tcp_connect(const char *ip, u_short port, TCPSOCKETEVENTPROC *lpfnEventProc) 
549 { 
550     SOCKET connectSocket; 
551     struct sockaddr_in addr; 
552     int sockIdx;
553 
554     if (!g_maxSockets || !g_sockets) return -1;
555 
556     connectSocket = socket(AF_INET, SOCK_STREAM, 0); 
557     if (connectSocket == INVALID_SOCKET) return -1;
558 
559     memset(&addr, 0, sizeof(addr)); 
560     addr.sin_family = AF_INET; 
561     addr.sin_addr.s_addr = ADDR_ANY; 
562     addr.sin_port = htons(0); 
563     if (bind(connectSocket, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) 
564     { 
565         closesocket(connectSocket); 
566         return -1; 
567     }
568 
569     sockIdx = tcp_new(TCP_TYPE_OUT); 
570     if (sockIdx < 0) 
571     { 
572         closesocket(connectSocket); 
573         return -1; 
574     }
575 
576     g_sockets[sockIdx]->sock = connectSocket; 
577     g_sockets[sockIdx]->lpfnEventProc = (lpfnEventProc ? lpfnEventProc : g_lpfnEventProc); 
578     CreateIoCompletionPort((HANDLE)g_sockets[sockIdx]->sock, g_completionPort, (ULONG_PTR)sockIdx, 0);
579 
580     memset(&g_sockets[sockIdx]->addr, 0, sizeof(addr)); 
581     g_sockets[sockIdx]->addr.sin_family = AF_INET; 
582     g_sockets[sockIdx]->addr.sin_addr.s_addr = inet_addr(ip); 
583     g_sockets[sockIdx]->addr.sin_port = htons(port);
584 
585     g_sockets[sockIdx]->stat |= STAT_CONNECTING;
586 
587     if (!g_lpfnConnectEx(g_sockets[sockIdx]->sock, 
588         (struct sockaddr *)&g_sockets[sockIdx]->addr, sizeof(g_sockets[sockIdx]->addr), 
589         NULL, 0, NULL, (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpConnect) 
590         && WSAGetLastError() != ERROR_IO_PENDING) 
591     { 
592         g_sockets[sockIdx]->stat |= STAT_CLOSING; // no notify 
593         PostQueuedCompletionStatus(g_completionPort, 0, sockIdx, 
594             (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpClose); 
595         return -1; 
596     }
597 
598     return sockIdx; 
599 }
600 
601 static BOOL tcp_processReceivedData(int sockIdx) 
602 { 
603     INT continueProcess, processed;
604 
605     continueProcess = 1; 
606     do 
607     { 
608         processed = g_sockets[sockIdx]->lpfnEventProc(sockIdx, TCP_EV_RECEIVE, 
609             g_sockets[sockIdx]->bufRecv.data, g_sockets[sockIdx]->bufRecv.dlen); 
610         if (processed < 0) 
611         { 
612             g_sockets[sockIdx]->stat |= STAT_CLOSING; 
613             PostQueuedCompletionStatus(g_completionPort, 0, sockIdx, 
614                 (LPOVERLAPPED)&g_sockets[sockIdx]->ovlpClose); 
615             continueProcess = -1; 
616         } 
617         else if (processed > 0) 
618         { 
619             buf_erase(&g_sockets[sockIdx]->bufRecv, 0, processed); 
620             continueProcess = (g_sockets[sockIdx]->bufRecv.dlen > 0 ? 1 : 0); 
621         } 
622         else 
623             continueProcess = 0; 
624     } 
625     while (continueProcess == 1);
626 
627     return continueProcess != -1; 
628 }
629 
630 static void tcp_checkIdleClients() 
631 { 
632     static time_t _lastCheckTime = 0; 
633     time_t currTime;
634 
635     time(&currTime); 
636     if (currTime - _lastCheckTime < 2) return; 
637     _lastCheckTime = currTime;
638 
639     if (g_sockets) 
640     { 
641         int i;
642 
643         for (i=0; i<g_maxSockets; i++) 
644         { 
645             if (!g_sockets[i]) break; 
646             if (g_sockets[i]->type != TCP_TYPE_IN) continue;
647 
648             if (!g_sockets[i]->lastReceiveTime && 
649                 currTime - g_sockets[i]->acceptTime >= 20) 
650                 tcp_release(i, FALSE); 
651         } 
652     } 
653 }
654 
655 #define IsValidSockIdx(sockIdx) (sockIdx >= 0 && sockIdx < g_maxSockets && g_sockets[sockIdx])
656 
657 static unsigned __stdcall tcp_workerThread(void* pArguments) 
658 { 
659     BOOL hasEntry; 
660     OVERLAPPED *lpo; 
661     DWORD dwBytes; 
662     ULONG_PTR key; 
663     int sockIdx, sockIdxAccepted, lastErr; 
664     DWORD currTickCount, nextTimerTickCount;
665 
666     nextTimerTickCount = GetTickCount() + 200;
667 
668     while (1) 
669     { 
670         hasEntry = GetQueuedCompletionStatus(g_completionPort, &dwBytes, &key, &lpo, 100);
671 
672         currTickCount = GetTickCount(); 
673         if (currTickCount > nextTimerTickCount) 
674         { 
675             nextTimerTickCount = currTickCount + 100; 
676             if (g_lpfnEventProc) 
677                 g_lpfnEventProc(-1, TCP_EV_TIMER, NULL, 0); 
678         }
679 
680         if (!lpo && !hasEntry) 
681         { 
682             lastErr = GetLastError(); 
683             //if (lastErr && lastErr != WAIT_TIMEOUT && lastErr != ERROR_IO_PENDING) ;
684 
685             tcp_checkIdleClients(); 
686             continue; 
687         }
688 
689         sockIdx = (int)key;
690 
691         if (lpo == &g_ovlpExit) break;
692 
693         if (sockIdx == -11) // custom event 
694         { 
695             if (g_lpfnEventProc) 
696                 g_lpfnEventProc(0, TCP_EV_CUSTOM, (UCHAR *)lpo, 0); 
697             continue; 
698         }
699 
700         if (sockIdx == -111) // timer event 
701         { 
702             currTickCount = GetTickCount(); 
703             if (currTickCount > nextTimerTickCount) 
704             { 
705                 nextTimerTickCount = currTickCount + 100; 
706                 if (g_lpfnEventProc) 
707                     g_lpfnEventProc(-1, TCP_EV_TIMER, NULL, 0); 
708             } 
709             continue; 
710         }
711 
712         if (!hasEntry) // IO operation failed, ie: socket closed 
713         { 
714             if (IsValidSockIdx(sockIdx)) 
715             { 
716                 if (g_sockets[sockIdx]->type == TCP_TYPE_LISTEN) 
717                     tcp_accept(sockIdx); 
718                 else 
719                     tcp_release(sockIdx, TRUE); 
720             } 
721             continue; 
722         }
723 
724         if (!IsValidSockIdx(sockIdx)) continue;
725 
726         if (lpo == &g_sockets[sockIdx]->ovlpConnect) 
727         { 
728             if (g_sockets[sockIdx]->stat & STAT_CONNECTING && 
729                 g_sockets[sockIdx]->type == TCP_TYPE_OUT) 
730             { 
731                 g_sockets[sockIdx]->stat &= ~STAT_CONNECTING; 
732                 time(&g_sockets[sockIdx]->connectTime);
733 
734                 if (g_sockets[sockIdx]->lpfnEventProc(sockIdx, TCP_EV_CONNECT, NULL, 0) < 0) 
735                     tcp_release(sockIdx, FALSE); 
736                 else 
737                     tcp_doReceive(sockIdx); 
738             } 
739         } 
740         else if (lpo == &g_sockets[sockIdx]->ovlpClose) 
741         { 
742             tcp_release(sockIdx, g_sockets[sockIdx]->stat & STAT_CLOSING); 
743         } 
744         else if (lpo == &g_sockets[sockIdx]->ovlpSend) 
745         { 
746             g_sockets[sockIdx]->stat &= ~STAT_SENDING;
747 
748             time(&g_sockets[sockIdx]->lastSendTime);
749 
750             // socket关闭以后仍然可能收到此消息 
751             //if (dwBytes != g_sockets[sockIdx]->bufSending.dlen);
752 
753             g_sockets[sockIdx]->bufSending.dlen = 0;
754 
755             if (!(g_sockets[sockIdx]->stat & STAT_CLOSING)) 
756             { 
757                 if (!g_sockets[sockIdx]->bufToSend.dlen) 
758                     g_sockets[sockIdx]->lpfnEventProc(sockIdx, TCP_EV_SEND, NULL, 0); 
759                 else 
760                 { 
761                     buf_swap(&g_sockets[sockIdx]->bufToSend, &g_sockets[sockIdx]->bufSending); 
762                     tcp_send(sockIdx, NULL, 0, NULL, 0); 
763                 } 
764             } 
765         } 
766         else if (lpo == &g_sockets[sockIdx]->ovlpReceive) 
767         { 
768             switch (g_sockets[sockIdx]->type) 
769             { 
770             case TCP_TYPE_LISTEN: 
771                 sockIdxAccepted = g_sockets[sockIdx]->sockIdxAccept; 
772                 g_sockets[sockIdxAccepted]->type = TCP_TYPE_IN; 
773                 setsockopt(g_sockets[sockIdxAccepted]->sock, 
774                     SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 
775                     (char *)&g_sockets[sockIdx]->sock, sizeof(SOCKET)); 
776                 CreateIoCompletionPort((HANDLE)g_sockets[sockIdxAccepted]->sock, 
777                     g_completionPort, (ULONG_PTR)sockIdxAccepted, 0); 
778                 time(&g_sockets[sockIdxAccepted]->acceptTime); 
779                 g_sockets[sockIdx]->lpfnEventProc(sockIdxAccepted, TCP_EV_ACCEPT, NULL, 0); 
780                 tcp_doReceive(sockIdxAccepted); 
781                 tcp_accept(sockIdx); 
782                 break;
783 
784             case TCP_TYPE_IN: 
785             case TCP_TYPE_OUT: 
786                 if (dwBytes == 0) // peer closed 
787                     tcp_release(sockIdx, TRUE); 
788                 else 
789                 { 
790                     g_sockets[sockIdx]->stat &= ~STAT_RECEIVING; 
791                     time(&g_sockets[sockIdx]->lastReceiveTime); 
792                     g_sockets[sockIdx]->bufRecv.dlen += dwBytes;
793 
794                     if (g_sockets[sockIdx]->sock == INVALID_SOCKET || 
795                         g_sockets[sockIdx]->stat & 0x0F) 
796                         tcp_release(sockIdx, FALSE); 
797                     else if (tcp_processReceivedData(sockIdx) && 
798                         !(g_sockets[sockIdx]->stat & STAT_PAUSED)) 
799                         tcp_doReceive(sockIdx); 
800                 } 
801                 break; 
802             } 
803         } 
804     }
805 
806     return 0; 
807 }
808 
809 static BOOL tcp_prepare() 
810 { 
811     GUID guidConnectEx = WSAID_CONNECTEX; 
812     GUID guidAcceptEx = WSAID_ACCEPTEX; 
813     GUID guidDisconnectEx = WSAID_DISCONNECTEX; 
814     SOCKET tmpSocket; 
815     DWORD dwBytes;
816 
817     tmpSocket = socket(AF_INET, SOCK_STREAM, 0); 
818     if (tmpSocket == INVALID_SOCKET) return FALSE; 
819     WSAIoctl(tmpSocket, 
820         SIO_GET_EXTENSION_FUNCTION_POINTER, 
821         &guidConnectEx, 
822         sizeof(guidConnectEx), 
823         &g_lpfnConnectEx, 
824         sizeof(g_lpfnConnectEx), 
825         &dwBytes, 
826         NULL, 
827         NULL); 
828     WSAIoctl(tmpSocket, 
829         SIO_GET_EXTENSION_FUNCTION_POINTER, 
830         &guidAcceptEx, 
831         sizeof(guidAcceptEx), 
832         &g_lpfnAcceptEx, 
833         sizeof(g_lpfnAcceptEx), 
834         &dwBytes, 
835         NULL, 
836         NULL); 
837     WSAIoctl(tmpSocket, 
838         SIO_GET_EXTENSION_FUNCTION_POINTER, 
839         &guidDisconnectEx, 
840         sizeof(guidDisconnectEx), 
841         &g_lpfnDisconnectEx, 
842         sizeof(g_lpfnDisconnectEx), 
843         &dwBytes, 
844         NULL, 
845         NULL); 
846     closesocket(tmpSocket);
847 
848     return (g_lpfnConnectEx && g_lpfnAcceptEx && g_lpfnDisconnectEx); 
849 }
850 
851 BOOL tcp_startup(int maxSockets, TCPSOCKETEVENTPROC *lpfnEventProc) 
852 { 
853     if (g_maxSockets) return TRUE;
854 
855     if (!tcp_prepare()) return FALSE;
856 
857     if (maxSockets < 512) maxSockets = 512; 
858     if (maxSockets > 50*1024) maxSockets = 50*1024;
859 
860     if (!lpfnEventProc) return FALSE;
861 
862     g_maxSockets = maxSockets; 
863     g_lpfnEventProc = lpfnEventProc;
864 
865     g_completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0); 
866     if (g_completionPort == NULL) return FALSE;
867 
868     g_sockets = (struct tcp_socket **)calloc(g_maxSockets, sizeof(struct tcp_socket *)); 
869     if (!g_sockets) return FALSE;
870 
871     g_thread = (HANDLE)_beginthreadex(NULL, 0, tcp_workerThread, NULL, 0, NULL); 
872     if (!g_thread) return FALSE;
873 
874     return TRUE; 
875 }
876 
877 void tcp_cleanup() 
878 { 
879     int i;
880 
881     if (!g_maxSockets || !g_sockets) return;
882 
883     for (i=0; i<g_maxSockets; i++) 
884     { 
885         if (!g_sockets[i]) break; 
886         g_sockets[i]->stat |= STAT_CLOSING; 
887     } 
888     for (i=0; i<g_maxSockets; i++) 
889     { 
890         if (!g_sockets[i]) break; 
891         PostQueuedCompletionStatus(g_completionPort, 0, i, &g_sockets[i]->ovlpClose); 
892     }
893 
894     PostQueuedCompletionStatus(g_completionPort, 0, 0, &g_ovlpExit); 
895     WaitForSingleObject(g_thread, INFINITE); 
896     CloseHandle(g_thread); 
897     g_thread = NULL;
898 
899     CloseHandle(g_completionPort); 
900     g_completionPort = NULL;
901 
902     for (i=0; i<g_maxSockets; i++) 
903     { 
904         if (!g_sockets[i]) break;
905 
906         buf_free(&g_sockets[i]->bufSending); 
907         buf_free(&g_sockets[i]->bufToSend); 
908         buf_free(&g_sockets[i]->bufRecv); 
909         free(g_sockets[i]); 
910     } 
911     free(g_sockets); 
912     g_sockets = NULL; 
913     g_maxSockets = 0; 
914 }

 

以上代码是从“网游更新平台”中摘出,运行状况不错。

"网游更新平台"现已开源:https://github.com/zhaozongzhe/gmDev

posted on 2012-12-02 16:09  zhaozongzhe  阅读(1392)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3