Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1140193
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 网络与安全

2011-01-24 04:59:11

  1. #include <winsock2.h>
  2. #include <ws2tcpip.h>
  3. #include <mswsock.h>
  4. #include <windows.h>

  5. #include "resolve.h"
  6. #include "public.h"

  7. typedef SINGLE_LIST_HEADER SocketObjHeader;
  8. typedef SINGLE_LIST SocketObj;
  9. typedef SINGLE_LIST_HEADER ThreadObjHeader;
  10. typedef SINGLE_LIST ThreadObj;
  11. typedef DOUBLE_LIST_HEADER BufferObjHeader;
  12. typedef DOUBLE_LIST BufferObj;

  13. #define DEFAULT_OVERLAPPED_COUNT 5

  14. struct _SOCKET_OBJ;
  15. struct _THREAD_OBJ;

  16. int gOverlappedCount = DEFAULT_OVERLAPPED_COUNT;

  17. typedef struct _BUFFER_OBJ_EX {
  18.     WSAOVERLAPPED ol; // Overlapped structure

  19.     SOCKET sclient; // Used for AcceptEx client socket

  20.     char *buf; // Buffer for send/recv/AcceptEx
  21.     int buflen; // Length of the buffer

  22.     int operation; // Type of operation submitted
  23. #define OP_ACCEPT 0 // AcceptEx
  24. #define OP_READ 1 // WSARecv/WSARecvFrom
  25. #define OP_WRITE 2 // WSASend?WSASendTo

  26.     struct _SOCKET_OBJ *Socket; // SOCKET_OBJ that this I/O belongs to
  27.     struct _THREAD_OBJ *Thread; // THREAD_OBJ this I/O is assigned to

  28.     SOCKADDR_STORAGE addr; // Remote address (UDP)
  29.     int addrlen; // Remote address length

  30.     BufferObj bufDList;
  31. }BUFFER_OBJ_EX;

  32. typedef struct _SOCKET_OBJ
  33. {
  34.     SOCKET s; // Socket handle for client connection

  35.     int af, // Address family of socket (AF_INET or AF_INET6)
  36.                          bClosing; // Indicates socket is closing

  37.     volatile LONG OutstandingOps; // Number of outstanding overlapped ops

  38.     BUFFER_OBJ_EX **PendingAccepts; // Array of pending AcceptEx calls (listening socket only)

  39.     // Pointers to Microsoft specific extensions (listening socket only)
  40.     LPFN_ACCEPTEX lpfnAcceptEx;
  41.     LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs;

  42.     CRITICAL_SECTION SockCritSec; // Synchronize access to this SOCKET_OBJ

  43.     SocketObj next; // Used to chain SOCKET_OBJ together
  44. } SOCKET_OBJ;

  45. typedef struct _THREAD_OBJ
  46. {
  47.     DOUBLE_LIST_HEADER BufferList; // Linked list of all sockets allocated

  48.     int EventCount; // How many events are in the array to wait on?

  49.     HANDLE Event; // Used to signal new clients assigned
  50.                                        // to this thread
  51.     HANDLE Thread; // Handle to the curren thread

  52.     HANDLE Handles[MAXIMUM_WAIT_OBJECTS]; // Array of socket's event handles

  53.     CRITICAL_SECTION ThreadCritSec; // Protect access to SOCKET_OBJ lists

  54.     ThreadObj next; // Next thread object in list
  55. } THREAD_OBJ;

  56. CRITICAL_SECTION gThreadListCritSec;
  57. ThreadObjHeader threadobjHeader;

  58. void AssignIoToThread(BUFFER_OBJ_EX *buf);

  59. SOCKET_OBJ *GetSocketObj(SOCKET s, int af) {
  60.     SOCKET_OBJ *sockobj = NULL;

  61.     sockobj = (SOCKET_OBJ *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_OBJ));
  62.     if (sockobj == NULL)
  63.     {
  64.         fprintf(stderr, "GetSocketObj: HeapAlloc failed: %d\n", GetLastError());
  65.         ExitProcess(-1);
  66.     }

  67.     sockobj->s = s;
  68.     sockobj->af = af;

  69.     InitializeCriticalSection(&sockobj->SockCritSec);

  70.     return sockobj;
  71. }

  72. void FreeSocketObj(SOCKET_OBJ *obj)
  73. {
  74.     BUFFER_OBJ *ptr=NULL,
  75.                 *tmp=NULL;


  76.     if (obj->OutstandingOps != 0)
  77.     {
  78.         return;
  79.     }
  80.     if (obj->s != INVALID_SOCKET)
  81.     {
  82.         closesocket(obj->s);
  83.         obj->s = INVALID_SOCKET;
  84.     }

  85.     DeleteCriticalSection(&obj->SockCritSec);

  86.     HeapFree(GetProcessHeap(), 0, obj);
  87. }

  88. BUFFER_OBJ_EX *GetBufferObjEx(SOCKET_OBJ *sock, int buflen) {
  89.     BUFFER_OBJ_EX *newobj = NULL;

  90.     newobj = (BUFFER_OBJ_EX *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BUFFER_OBJ_EX));
  91.     if (newobj == NULL)
  92.     {
  93.         fprintf(stderr, "GetBufferObj: HeapAlloc failed: %d\n", GetLastError());
  94.         ExitProcess(-1);
  95.     }

  96.     newobj->buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BYTE) *buflen);
  97.     if (newobj->buf == NULL)
  98.     {
  99.         fprintf(stderr, "GetBufferObj: HeapAlloc failed: %d\n", GetLastError());
  100.         ExitProcess(-1);
  101.     }
  102.     newobj->buflen = buflen;

  103.     newobj->addrlen = sizeof(newobj->addr);
  104.     newobj->Socket = sock;

  105.     newobj->ol.hEvent = WSACreateEvent();
  106.     if (newobj->ol.hEvent == NULL) {
  107.         fprintf(stderr, "WSACreateEvent failed.\n");
  108.         ExitProcess(-1);
  109.     }

  110.     return newobj;
  111. }

  112. BUFFER_OBJ_EX *FindBufferObjEx(THREAD_OBJ *thread, WSAEVENT hEvent) {
  113.     BufferObj *ptr=NULL;
  114.     BUFFER_OBJ_EX *bufobj = NULL;

  115.     EnterCriticalSection(&thread->ThreadCritSec);

  116.     ptr = (BufferObj *)GotoNextDoubleList(&(thread->BufferList), &(thread->BufferList.head));
  117.     while (ptr) {
  118.         bufobj = (BUFFER_OBJ_EX *)container_of(BUFFER_OBJ_EX, bufDList, ptr);

  119.         if (bufobj->ol.hEvent == hEvent)
  120.             break;

  121.         ptr = (BufferObj *)GotoNextDoubleList(&(thread->BufferList), ptr);
  122.     }

  123.     LeaveCriticalSection(&thread->ThreadCritSec);

  124.     return bufobj;
  125. }

  126. void FreeBufferObjEx(BUFFER_OBJ_EX *obj)
  127. {
  128.     // Close the event
  129.     WSACloseEvent(obj->ol.hEvent);
  130.     obj->ol.hEvent = NULL;
  131.     // Free the buffers
  132.     HeapFree(GetProcessHeap(), 0, obj->buf);
  133.     HeapFree(GetProcessHeap(), 0, obj);
  134. }

  135. int InsertBufferObjExToThread(THREAD_OBJ *thread, BUFFER_OBJ_EX *buf) {
  136.     int ret;

  137.     EnterCriticalSection(&thread->ThreadCritSec);

  138.     if (thread->EventCount < MAXIMUM_WAIT_OBJECTS - 1) {
  139.         EnqueueDoubleList(&(thread->BufferList), &(buf->bufDList));
  140.         thread->Handles[thread->EventCount++] = buf->ol.hEvent;

  141.         ret = NO_ERROR;
  142.     } else {
  143.         ret = SOCKET_ERROR;
  144.     }

  145.     LeaveCriticalSection(&thread->ThreadCritSec);

  146.     return ret;
  147. }

  148. void RemoveBufferFromThread(SOCKET_OBJ *sock, BUFFER_OBJ_EX *buf)
  149. {
  150.     EnterCriticalSection(&buf->Thread->ThreadCritSec);

  151.     // Remove buffer from the list
  152.     RemoveDoubleList(&buf->Thread->BufferList, &buf->bufDList);
  153.     // Decrement the event count for the thread
  154.     buf->Thread->EventCount--;
  155.     // Set the thread's event
  156.     WSASetEvent(buf->Thread->Event);

  157.     LeaveCriticalSection(&buf->Thread->ThreadCritSec);

  158. }

  159. THREAD_OBJ *GetThreadObj() {
  160.     THREAD_OBJ *thread = NULL;

  161.     thread = (THREAD_OBJ *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THREAD_OBJ));
  162.     if (thread == NULL) {
  163.         fprintf(stderr, "GetThreadObj:HeapAlloc failed.\n");
  164.         ExitProcess(-1);
  165.     }

  166.     thread->Event = WSACreateEvent();
  167.     if (thread->Event == NULL) {
  168.         fprintf(stderr, "GetThreadObj: WSACreateEvent failed.\n");
  169.         ExitProcess(-1);
  170.     }

  171.     thread->Handles[0] = thread->Event;
  172.     thread->EventCount = 1;

  173.     InitializeDoubleHead(&thread->BufferList);

  174.     InitializeCriticalSection(&thread->ThreadCritSec);

  175.     return thread;
  176. }

  177. void RenumberEvents(THREAD_OBJ *thread) {
  178.     EnterCriticalSection(&thread->ThreadCritSec);

  179.     BUFFER_OBJ_EX *obj = NULL;
  180.     int i = 0;

  181.     BufferObj *sptr = NULL;
  182.     sptr = (BufferObj *)GotoNextDoubleList(&(thread->BufferList), &(thread->BufferList.head));
  183.     thread->EventCount = 1;
  184.     while (sptr) {
  185.         obj = (BUFFER_OBJ_EX *)container_of(BUFFER_OBJ_EX, bufDList, sptr);

  186.         thread->Handles[thread->EventCount++] = obj->ol.hEvent;

  187.         sptr = (BufferObj *)GotoNextDoubleList(&(thread->BufferList), sptr);
  188.     }

  189.     LeaveCriticalSection(&thread->ThreadCritSec);
  190. }

  191. int PostRecv(BUFFER_OBJ_EX *recvobj) {
  192.     WSABUF wbuf;
  193.     DWORD bytes,
  194.             flags;
  195.     int rc=NO_ERROR;

  196.     EnterCriticalSection(&recvobj->Socket->SockCritSec);

  197.     recvobj->operation = OP_READ;

  198.     wbuf.buf = recvobj->buf;
  199.     wbuf.len = recvobj->buflen;

  200.     flags = 0;

  201.     if (gProtocol == IPPROTO_TCP) {
  202.         rc = WSARecv(recvobj->Socket->s, &wbuf, 1, &bytes, &flags, &recvobj->ol, NULL);
  203.     }
  204.     else {
  205.         ExitProcess(-1);
  206.     }
  207.     if (rc == SOCKET_ERROR)
  208.     {
  209.         rc = NO_ERROR;
  210.         if (WSAGetLastError() != WSA_IO_PENDING)
  211.         {
  212.             fprintf(stderr, "PostRecv: WSARecv* failed: %d\n", WSAGetLastError());
  213.             rc = SOCKET_ERROR;
  214.         }
  215.     }

  216.     // Increment outstanding overlapped operations
  217.     InterlockedIncrement(&recvobj->Socket->OutstandingOps);

  218.     LeaveCriticalSection(&recvobj->Socket->SockCritSec);

  219.     return NO_ERROR;
  220. }

  221. int PostSend(BUFFER_OBJ_EX *sendobj) {
  222.     WSABUF wbuf;
  223.     DWORD bytes;
  224.     int rc;

  225.     rc = NO_ERROR;

  226.     sendobj->operation = OP_WRITE;

  227.     wbuf.buf = sendobj->buf;
  228.     wbuf.len = sendobj->buflen;

  229.     EnterCriticalSection(&sendobj->Socket->SockCritSec);
  230.     if (gProtocol == IPPROTO_TCP) {
  231.         rc = WSASend(sendobj->Socket->s, &wbuf, 1, &bytes, 0, &sendobj->ol, NULL);
  232.     }
  233.     else {
  234.         ExitProcess(-1);
  235.     }
  236.     if (rc == SOCKET_ERROR)
  237.     {
  238.         rc = NO_ERROR;
  239.         if (WSAGetLastError() != WSA_IO_PENDING)
  240.         {
  241.             fprintf(stderr, "PostSend: WSASend* failed: %d\n", WSAGetLastError());
  242.             rc = SOCKET_ERROR;
  243.         }
  244.     }

  245.     // Increment the outstanding operation count
  246.     InterlockedIncrement(&sendobj->Socket->OutstandingOps);

  247.     LeaveCriticalSection(&sendobj->Socket->SockCritSec);

  248.     return rc;
  249. }

  250. int PostAccept(BUFFER_OBJ_EX *acceptobj) {
  251.     DWORD bytes;
  252.     int rc = NO_ERROR;

  253.     acceptobj->operation = OP_ACCEPT;

  254.     EnterCriticalSection(&acceptobj->Socket->SockCritSec);

  255.     acceptobj->sclient = socket(acceptobj->Socket->af, SOCK_STREAM, IPPROTO_TCP);
  256.     if (acceptobj->sclient == INVALID_SOCKET) {
  257.         fprintf(stderr, "PostAccept: create socket failed.\n");
  258.         return -1;
  259.     }

  260.     rc = acceptobj->Socket->lpfnAcceptEx(acceptobj->Socket->s, acceptobj->sclient, acceptobj->buf,
  261.         acceptobj->buflen - ((sizeof(SOCKADDR_STORAGE) + 16) * 2), sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16,
  262.            &bytes, &acceptobj->ol);
  263.     if (rc == FALSE) {
  264.         if (WSAGetLastError() != WSA_IO_PENDING)
  265.         {
  266.             fprintf(stderr, "PostAccept: AcceptEx failed: %d\n", WSAGetLastError());
  267.             ExitProcess(-1);
  268.         }
  269.     }

  270.     InterlockedIncrement(&acceptobj->Socket->OutstandingOps);

  271.     LeaveCriticalSection(&acceptobj->Socket->SockCritSec);

  272.     return rc;
  273. }

  274. void HandleIo(BUFFER_OBJ_EX *buf) {
  275.     SOCKET_OBJ *sock=NULL,
  276.                     *clientobj=NULL; // New client object for accepted connections
  277.     BUFFER_OBJ_EX *recvobj=NULL, // Used to post new receives on accepted connections
  278.                     *sendobj=NULL; // Used to post sends for data received
  279.     DWORD bytes,
  280.                      flags;
  281.     BOOL bFreeSocketObj;
  282.     int error,
  283.                      rc;

  284.     sock = buf->Socket;
  285.     error = NO_ERROR;

  286.     bFreeSocketObj = FALSE;

  287.     InterlockedDecrement(&sock->OutstandingOps);

  288.     rc = WSAGetOverlappedResult(sock->s, &buf->ol, &bytes, FALSE, &flags);
  289.     if (rc == FALSE) {
  290.         fprintf(stderr, "HandleIo: WSAGetOverlappedResult failed.\n");
  291.         ExitProcess(-1);
  292.     }

  293.     if (buf->operation == OP_ACCEPT) {
  294.         SOCKADDR_STORAGE *LocalSockaddr=NULL,
  295.                          *RemoteSockaddr=NULL;
  296.         int LocalSockaddrLen,
  297.                           RemoteSockaddrLen;

  298.         sock->lpfnGetAcceptExSockaddrs(buf->buf, buf->buflen - ((sizeof(SOCKADDR_STORAGE) + 16) * 2),
  299.                 sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16,
  300.                 (SOCKADDR **)&LocalSockaddr, &LocalSockaddrLen,
  301.                 (SOCKADDR **)&RemoteSockaddr, &RemoteSockaddrLen);

  302.         clientobj = GetSocketObj(buf->sclient, buf->Socket->af);
  303.         sendobj = GetBufferObjEx(clientobj, gBufferSize);

  304.         sendobj->buflen = bytes;
  305.         memcpy(sendobj->buf, buf->buf, bytes);

  306.         AssignIoToThread(sendobj);

  307.         if (PostSend(sendobj) != NO_ERROR) {
  308.             RemoveBufferFromThread(clientobj, sendobj);
  309.             FreeBufferObjEx(sendobj);

  310.             closesocket(clientobj->s);
  311.             clientobj->s = INVALID_SOCKET;

  312.             FreeSocketObj(clientobj);
  313.         }

  314.         PostAccept(buf);
  315.     } else if ((buf->operation == OP_READ) && (error == NO_ERROR)) {
  316.         if ((bytes > 0) || (gProtocol == IPPROTO_UDP))
  317.         {
  318.             // Create a buffer to send
  319.             sendobj = buf;

  320.             sendobj->buflen = bytes;

  321.             // Initiate the send
  322.             if (PostSend(sendobj) != NO_ERROR)
  323.             {
  324.                 // In the event of an error, clean up the socket object
  325.                 RemoveBufferFromThread(sock, sendobj);
  326.                 FreeBufferObjEx(sendobj);

  327.                 closesocket(sock->s);
  328.                 sock->s = INVALID_SOCKET;

  329.                 bFreeSocketObj = TRUE;
  330.             }
  331.         }
  332.         else
  333.         {
  334.             // Graceful close
  335.             sock->bClosing = TRUE;

  336.             // Free the completed operation
  337.             RemoveBufferFromThread(sock, buf);
  338.             FreeBufferObjEx(buf);

  339.             // Check to see if there are more outstanding operations. If so, wait
  340.             // for them to complete; otherwise, clean up the socket object.
  341.             EnterCriticalSection(&sock->SockCritSec);
  342.             if (sock->OutstandingOps == 0)
  343.             {
  344.                 closesocket(sock->s);

  345.                 bFreeSocketObj = TRUE;
  346.             }
  347.             LeaveCriticalSection(&sock->SockCritSec);
  348.         }
  349.     } else if (buf->operation == OP_WRITE) {
  350.         EnterCriticalSection(&sock->SockCritSec);
  351.         if (sock->bClosing && (sock->OutstandingOps == 0))
  352.         {
  353.             RemoveBufferFromThread(sock, buf);
  354.             closesocket(sock->s);
  355.             FreeBufferObjEx(buf);

  356.             bFreeSocketObj = TRUE;
  357.         }
  358.         else
  359.         {
  360.             buf->buflen = gBufferSize;

  361.             // Free the send op that just completed
  362.             if (PostRecv(buf) != NO_ERROR)
  363.             {
  364.                 RemoveBufferFromThread(sock, buf);
  365.                 FreeBufferObjEx(buf);
  366.             }
  367.         }
  368.         LeaveCriticalSection(&sock->SockCritSec);
  369.     }
  370. }

  371. DWORD WINAPI IoThread(LPVOID lpParam) {
  372.     THREAD_OBJ *thread=NULL;
  373.     int index,
  374.                      count,
  375.                      rc,
  376.                      i;

  377.     thread = (THREAD_OBJ *)lpParam;

  378.     RenumberEvents(thread);

  379.     while (true) {
  380.         rc = WaitForMultipleObjects(thread->EventCount, thread->Handles, FALSE, INFINITE);
  381.         if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT) {
  382.             if (GetLastError() == ERROR_INVALID_HANDLE)
  383.             {
  384.                 RenumberEvents(thread);
  385.                 continue;
  386.             }
  387.             else
  388.             {
  389.                 fprintf(stderr, "IoThread: WaitForMultipleObjects failed: %d\n",
  390.                         GetLastError());
  391.                 break;
  392.             }
  393.         }

  394.         count = thread->EventCount;
  395.         for (i = 0; i < count; ++i) {
  396.             rc = WaitForSingleObject(thread->Handles[i], 0);
  397.             if (rc == WAIT_TIMEOUT)
  398.                 continue;

  399.             index = i;
  400.             WSAResetEvent(thread->Handles[index]);

  401.             if (index == 0) {
  402.                 RenumberEvents(thread);
  403.                 break;
  404.             } else {
  405.                 HandleIo(FindBufferObjEx(thread, thread->Handles[index]));
  406.             }
  407.         }
  408.     }

  409.     ExitThread(0);
  410.     return 0;
  411. }

  412. void AssignIoToThread(BUFFER_OBJ_EX *buf) {
  413.     ThreadObj *threadObj;
  414.     THREAD_OBJ *thread;

  415.     EnterCriticalSection(&gThreadListCritSec);

  416.     threadObj = (ThreadObj *)GotoNextSingleList(&threadobjHeader, threadobjHeader.head);
  417.     while (threadObj) {
  418.         thread = (THREAD_OBJ *)container_of(THREAD_OBJ, next, threadObj);

  419.         if (InsertBufferObjExToThread(thread, buf) == NO_ERROR) {
  420.             break;
  421.         }

  422.         threadObj = (ThreadObj *)GotoNextSingleList(&threadobjHeader, threadObj);
  423.     }

  424.     if (threadObj == NULL) {
  425.         thread = GetThreadObj();

  426.         thread->Thread = CreateThread(NULL, 0, IoThread, (LPVOID)thread, 0, NULL);
  427.         if (thread->Thread == NULL) {
  428.             fprintf(stderr, "AssignIoToThread: CreateThread failed.\n");
  429.             ExitProcess(-1);
  430.         }

  431.         InsertBufferObjExToThread(thread, buf);
  432.         EnqueueSingleListHead(&threadobjHeader, &(thread->next));
  433.     }

  434.     buf->Thread = thread;

  435.     WSASetEvent(thread->Event);

  436.     LeaveCriticalSection(&gThreadListCritSec);
  437. }

  438. int _tmain(int argc, _TCHAR* argv[])
  439. {
  440.     WSADATA wsd;
  441.     THREAD_OBJ *thread=NULL;
  442.     SOCKET_OBJ *sockobj=NULL;
  443.     SocketObjHeader ListenSockets;
  444.     int endpointcount=0,
  445.                      interval = 0,
  446.                      rc,
  447.                      i;
  448.     struct addrinfo *res=NULL,
  449.                     *ptr=NULL;

  450.     if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
  451.     {
  452.         fprintf(stderr, "unable to load Winsock!\n");
  453.         return -1;
  454.     }

  455.     InitializeCriticalSection(&gThreadListCritSec);
  456.     InitializeSingleHead(&ListenSockets);
  457.     InitializeSingleHead(&threadobjHeader);

  458.     res = ResolveAddress(gSrvAddr, gPort, gAddressFamily, gSocketType, gProtocol);
  459.     if (res == NULL)
  460.     {
  461.         fprintf(stderr, "ResolveAddress failed to return any addresses!\n");
  462.         return -1;
  463.     }

  464.     ptr = res;
  465.     while (ptr) {
  466.         sockobj = GetSocketObj(INVALID_SOCKET, ptr->ai_family);

  467.         sockobj->s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  468.         if (sockobj->s == INVALID_SOCKET)
  469.         {
  470.             fprintf(stderr,"socket failed: %d\n", WSAGetLastError());
  471.             return -1;
  472.         }

  473.         rc = bind(sockobj->s, ptr->ai_addr, ptr->ai_addrlen);
  474.         if (rc == SOCKET_ERROR)
  475.         {
  476.             fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
  477.             return -1;
  478.         }

  479.         if (gProtocol == IPPROTO_TCP) {
  480.             BUFFER_OBJ_EX *acceptobj = NULL;
  481.             GUID guidAcceptEx = WSAID_ACCEPTEX,
  482.                  guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
  483.             DWORD bytes;

  484.             rc = WSAIoctl(sockobj->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, sizeof(guidAcceptEx),
  485.                 &sockobj->lpfnAcceptEx, sizeof(sockobj->lpfnAcceptEx), &bytes, NULL, NULL);
  486.             if (rc == SOCKET_ERROR)
  487.             {
  488.                 fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n",
  489.                         WSAGetLastError());
  490.                 return -1;
  491.             }

  492.             rc = WSAIoctl(sockobj->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidGetAcceptExSockaddrs, sizeof(guidGetAcceptExSockaddrs),
  493.                 &sockobj->lpfnGetAcceptExSockaddrs, sizeof(sockobj->lpfnGetAcceptExSockaddrs), &bytes, NULL, NULL);
  494.             if (rc == SOCKET_ERROR)
  495.             {
  496.                 fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n",
  497.                         WSAGetLastError());
  498.                 return -1;
  499.             }

  500.             rc = listen(sockobj->s, 200);
  501.             if (rc == SOCKET_ERROR)
  502.             {
  503.                 fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
  504.                 return -1;
  505.             }

  506.             sockobj->PendingAccepts = (BUFFER_OBJ_EX **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(BUFFER_OBJ *) * gOverlappedCount));
  507.             if (sockobj->PendingAccepts == NULL)
  508.             {
  509.                 fprintf(stderr, "PendingAccepts HeapAlloc failed: %d\n", GetLastError());
  510.                 ExitProcess(-1);
  511.             }
  512.             for (i = 0; i < gOverlappedCount; ++i) {
  513.                 sockobj->PendingAccepts[i] = acceptobj = GetBufferObjEx(sockobj, gBufferSize);
  514.                 AssignIoToThread(acceptobj);

  515.                 if (PostAccept(acceptobj) != NO_ERROR) {
  516.                     ExitProcess(-1);
  517.                 }
  518.             }

  519.             EnqueueSingleList(&ListenSockets, &(sockobj->next));
  520.         }


  521.         ptr = ptr->ai_next;
  522.     }

  523.     freeaddrinfo(res);

  524.     while (true) {
  525.         Sleep(5000);

  526.         interval++;

  527.         if (interval == 12) {
  528.             SocketObj *listenptr=NULL;
  529.             int optval,
  530.                          optlen;

  531.             // Walk the list of outstanding accepts
  532.             listenptr = (SocketObj *)GotoNextSingleList(&ListenSockets, ListenSockets.head);
  533.             while (listenptr)
  534.             {
  535.                 sockobj = (SOCKET_OBJ *)container_of(SOCKET_OBJ, next, listenptr);
  536.                 for(i=0; i < gOverlappedCount ;i++)
  537.                 {
  538.                     optlen = sizeof(optval);
  539.                     rc = getsockopt(
  540.                             sockobj->PendingAccepts[i]->sclient,
  541.                             SOL_SOCKET,
  542.                             SO_CONNECT_TIME,
  543.                             (char *)&optval,
  544.                            &optlen
  545.                            );
  546.                     if (rc == SOCKET_ERROR)
  547.                     {
  548.                         fprintf(stderr, "getsockopt: SO_CONNECT_TIME failed: %d\n", WSAGetLastError());
  549.                         return -1;
  550.                     }
  551.                     if ((optval != 0xFFFFFFFF) && (optval > 300))
  552.                     {
  553.                         closesocket(sockobj->PendingAccepts[i]->sclient);
  554.                     }
  555.                 }
  556.                 listenptr = (SocketObj *)GotoNextSingleList(&ListenSockets, listenptr);
  557.             }
  558.             interval = 0;
  559.         }
  560.     }

  561.     WSACleanup();

  562.     return 0;
  563. }
阅读(2667) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~