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

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 系统运维

2011-01-26 01:12:43

  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. #define DEFAULT_OVERLAPPED_COUNT 5
  8. #define MAX_COMPLETION_THREAD_COUNT 32 // Maximum number of completion threads allowed

  9. typedef SINGLE_LIST_HEADER SocketObjHeader;
  10. typedef SINGLE_LIST SocketObj;
  11. typedef DOUBLE_LIST_HEADER BufferObjHeader;
  12. typedef DOUBLE_LIST BufferObj;

  13. int gOverlappedCount = DEFAULT_OVERLAPPED_COUNT;

  14. typedef struct _BUFFER_OBJ_EX {
  15.     WSAOVERLAPPED ol; // Overlapped structure

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

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

  19.     int operation; // Type of operation submitted
  20. #define OP_ACCEPT 0 // AcceptEx
  21. #define OP_READ 1 // WSARecv/WSARecvFrom
  22. #define OP_WRITE 2 // WSASend?WSASendTo

  23.     SOCKADDR_STORAGE addr; // Remote address (UDP)
  24.     int addrlen; // Remote address length

  25.     ULONG IoOrder; // Order in which this I/O was posted

  26.     BufferObj bufDList;
  27. }BUFFER_OBJ_EX;

  28. typedef struct _SOCKET_OBJ
  29. {
  30.     SOCKET s; // Socket handle for client connection

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

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

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

  35.     ULONG LastSendIssued, // Last sequence number sent
  36.                          IoCountIssued; // Next sequence number assigned to receives
  37.     BufferObjHeader OutOfOrderSends;// List of send buffers that completed out of order

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

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

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

  44. SOCKET_OBJ *GetSocketObj(SOCKET s, int af)
  45. {
  46.     SOCKET_OBJ *sockobj=NULL;

  47.     sockobj = (SOCKET_OBJ *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_OBJ));
  48.     if (sockobj == NULL)
  49.     {
  50.         fprintf(stderr, "GetSocketObj: HeapAlloc failed: %d\n", GetLastError());
  51.         ExitProcess(-1);
  52.     }

  53.     InitializeCriticalSection(&sockobj->SockCritSec);
  54.     InitializeDoubleHead(&sockobj->OutOfOrderSends);

  55.     sockobj->IoCountIssued = ((gProtocol == IPPROTO_TCP) ? 1 : 0);

  56.     // Initialize the members
  57.     sockobj->s = s;
  58.     sockobj->af = af;

  59.     return sockobj;
  60. }

  61. BUFFER_OBJ_EX *GetBufferObjEx(int buflen)
  62. {
  63.     BUFFER_OBJ_EX *newobj=NULL;

  64.     // Allocate the object
  65.     newobj = (BUFFER_OBJ_EX *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BUFFER_OBJ_EX));
  66.     if (newobj == NULL) {
  67.         printf("GetBufferObj: HeapAlloc failed: %d\n", GetLastError());
  68.         ExitProcess(-1);
  69.     }

  70.     // Allocate the buffer
  71.     newobj->buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BYTE) *buflen);
  72.     if (newobj->buf == NULL) {
  73.         printf("GetBufferObj: HeapAlloc failed: %d\n", GetLastError());
  74.         ExitProcess(-1);
  75.     }

  76.     newobj->buflen = buflen;
  77.     newobj->addrlen = sizeof(newobj->addr);

  78.     return newobj;
  79. }

  80. void FreeBufferObjEx(BUFFER_OBJ_EX *obj)
  81. {
  82.     HeapFree(GetProcessHeap(), 0, obj->buf);
  83.     HeapFree(GetProcessHeap(), 0, obj);
  84. }

  85. void FreeSocketObj(SOCKET_OBJ *obj)
  86. {
  87.     BUFFER_OBJ_EX *ptr=NULL,
  88.                 *tmp=NULL;

  89.     if (obj->OutstandingOps != 0)
  90.     {
  91.         // Still outstanding operations so just return
  92.         return;
  93.     }
  94.     // Close the socket if it hasn't already been closed
  95.     if (obj->s != INVALID_SOCKET)
  96.     {
  97.         closesocket(obj->s);
  98.         obj->s = INVALID_SOCKET;
  99.     }

  100.     DeleteCriticalSection(&obj->SockCritSec);

  101.     HeapFree(GetProcessHeap(), 0, obj);
  102. }

  103. void InsertPendingSend(SOCKET_OBJ *sock, BUFFER_OBJ_EX *send)
  104. {
  105.     BufferObj *ptr = NULL;
  106.     BUFFER_OBJ_EX *obj = NULL;

  107.     EnterCriticalSection(&sock->SockCritSec);

  108.     ptr = (BufferObj *)GotoNextDoubleList(&sock->OutOfOrderSends, &sock->OutOfOrderSends.head);
  109.     while (ptr)
  110.     {
  111.         obj = (BUFFER_OBJ_EX *)container_of(BUFFER_OBJ_EX, bufDList, ptr);
  112.         if (send->IoOrder < obj->IoOrder)
  113.         {
  114.             break;
  115.         }

  116.         ptr = (BufferObj *)GotoNextDoubleList(&sock->OutOfOrderSends, ptr);
  117.     }
  118.     if (ptr == NULL)
  119.         ptr = &sock->OutOfOrderSends.head;

  120.     EnqueueDoubleListBefore(&sock->OutOfOrderSends, ptr, &send->bufDList);

  121.     LeaveCriticalSection(&sock->SockCritSec);
  122. }

  123. int PostRecv(SOCKET_OBJ *sock, BUFFER_OBJ_EX *recvobj)
  124. {
  125.     WSABUF wbuf;
  126.     DWORD bytes,
  127.             flags;
  128.     int rc;


  129.     recvobj->operation = OP_READ;

  130.     wbuf.buf = recvobj->buf;
  131.     wbuf.len = recvobj->buflen;

  132.     flags = 0;

  133.     EnterCriticalSection(&sock->SockCritSec);

  134.     // Assign the IO order to this receive. This must be performned within
  135.     // the critical section. The operation of assigning the IO count and posting
  136.     // the receive cannot be interupted.
  137.     recvobj->IoOrder = sock->IoCountIssued;
  138.     sock->IoCountIssued++;

  139.     if (gProtocol == IPPROTO_TCP)
  140.     {
  141.         rc = WSARecv(
  142.                 sock->s,
  143.                &wbuf,
  144.                 1,
  145.                &bytes,
  146.                &flags,
  147.                &recvobj->ol,
  148.                 NULL
  149.                 );
  150.     }
  151.     else
  152.     {
  153.         ExitProcess(-1);
  154.     }

  155.     LeaveCriticalSection(&sock->SockCritSec);

  156.     if (rc == SOCKET_ERROR)
  157.     {
  158.         if (WSAGetLastError() != WSA_IO_PENDING)
  159.         {
  160.             fprintf(stderr, "PostRecv: WSARecv* failed: %d\n", WSAGetLastError());
  161.             return SOCKET_ERROR;
  162.         }
  163.     }

  164.     // Increment outstanding overlapped operations
  165.     InterlockedIncrement(&sock->OutstandingOps);

  166.     return NO_ERROR;
  167. }

  168. int sendnum = 0;

  169. int PostSend(SOCKET_OBJ *sock, BUFFER_OBJ_EX *sendobj)
  170. {
  171.     WSABUF wbuf;
  172.     DWORD bytes;
  173.     int rc;

  174.     sendobj->operation = OP_WRITE;

  175.     wbuf.buf = sendobj->buf;
  176.     wbuf.len = sendobj->buflen;

  177.     EnterCriticalSection(&sock->SockCritSec);

  178.     // Incrmenting the last send issued and issuing the send should not be
  179.     // interuptable.
  180.     sock->LastSendIssued++;

  181.     if (gProtocol == IPPROTO_TCP)
  182.     {
  183.         printf("send %d\n", sendnum++);
  184.         rc = WSASend(
  185.                 sock->s,
  186.                &wbuf,
  187.                 1,
  188.                &bytes,
  189.                 0,
  190.                &sendobj->ol,
  191.                 NULL
  192.                 );
  193.     }
  194.     else {
  195.         ExitProcess(-1);
  196.     }

  197.     LeaveCriticalSection(&sock->SockCritSec);

  198.     if (rc == SOCKET_ERROR)
  199.     {
  200.         if (WSAGetLastError() != WSA_IO_PENDING)
  201.         {
  202.             fprintf(stderr, "PostSend: WSASend* failed: %d\n", WSAGetLastError());
  203.             return SOCKET_ERROR;
  204.         }
  205.     }

  206.     // Increment the outstanding operation count
  207.     InterlockedIncrement(&sock->OutstandingOps);

  208.     return NO_ERROR;
  209. }

  210. int PostAccept(SOCKET_OBJ *sock, BUFFER_OBJ_EX *acceptobj)
  211. {
  212.     DWORD bytes;
  213.     int rc;

  214.     acceptobj->operation = OP_ACCEPT;

  215.     // Create the client socket for an incoming connection
  216.     acceptobj->sclient = socket(sock->af, SOCK_STREAM, IPPROTO_TCP);
  217.     if (acceptobj->sclient == INVALID_SOCKET)
  218.     {
  219.         fprintf(stderr, "PostAccept: socket failed: %d\n", WSAGetLastError());
  220.         return -1;
  221.     }

  222.     rc = sock->lpfnAcceptEx(
  223.             sock->s,
  224.             acceptobj->sclient,
  225.             acceptobj->buf,
  226.             acceptobj->buflen - ((sizeof(SOCKADDR_STORAGE) + 16) * 2),
  227.             sizeof(SOCKADDR_STORAGE) + 16,
  228.             sizeof(SOCKADDR_STORAGE) + 16,
  229.            &bytes,
  230.            &acceptobj->ol
  231.             );
  232.     if (rc == FALSE)
  233.     {
  234.         if (WSAGetLastError() != WSA_IO_PENDING)
  235.         {
  236.             fprintf(stderr, "PostAccept: AcceptEx failed: %d\n", WSAGetLastError());
  237.             return SOCKET_ERROR;
  238.         }
  239.     }

  240.     // Increment the outstanding overlapped count for this socket
  241.     InterlockedIncrement(&sock->OutstandingOps);

  242.     return NO_ERROR;
  243. }

  244. int DoSends(SOCKET_OBJ *sock)
  245. {
  246.     BufferObj *ptr = NULL;
  247.     BufferObj *tmp = NULL;
  248.     BUFFER_OBJ_EX *sendobj = NULL;

  249.     int ret;

  250.     ret = NO_ERROR;

  251.     EnterCriticalSection(&sock->SockCritSec);

  252.     ptr = (BufferObj *)GotoNextDoubleList(&sock->OutOfOrderSends, &sock->OutOfOrderSends.head);
  253.     while (ptr) {
  254.         sendobj = (BUFFER_OBJ_EX *)container_of(BUFFER_OBJ_EX, bufDList, ptr);
  255.         if ((sendobj) && (sendobj->IoOrder == sock->LastSendIssued))
  256.         {
  257.             if (PostSend(sock, sendobj) != NO_ERROR)
  258.             {
  259.                 FreeBufferObjEx(sendobj);
  260.     
  261.                 ret = SOCKET_ERROR;
  262.                 break;
  263.             }
  264.         } else
  265.             break;
  266.         tmp = ptr;
  267.         ptr = (BufferObj *)GotoNextDoubleList(&sock->OutOfOrderSends, ptr);

  268.         RemoveDoubleList(&sock->OutOfOrderSends, tmp);
  269.         //FreeBufferObjEx(sendobj);
  270.     }

  271.     LeaveCriticalSection(&sock->SockCritSec);

  272.     return ret;
  273. }

  274. int handleNum = 0;
  275. int handlecut = 0;

  276. void HandleIo(SOCKET_OBJ *sock, BUFFER_OBJ_EX *buf, HANDLE CompPort, DWORD BytesTransfered, DWORD error) {
  277.     SOCKET_OBJ *clientobj=NULL; // New client object for accepted connections
  278.     BUFFER_OBJ_EX *recvobj=NULL, // Used to post new receives on accepted connections
  279.                *sendobj=NULL; // Used to post new sends for data received
  280.     BOOL bCleanupSocket;
  281.     char *tmp;
  282.     int i;

  283.     bCleanupSocket = FALSE;

  284.     if ((error != NO_ERROR) && (gProtocol == IPPROTO_TCP)) {
  285.         FreeBufferObjEx(buf);

  286.         if (InterlockedDecrement(&sock->OutstandingOps) == 0) {
  287.             FreeSocketObj(sock);
  288.         }
  289.         return;
  290.     }

  291.     EnterCriticalSection(&sock->SockCritSec);

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

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

  303.         clientobj = GetSocketObj(buf->sclient, sock->af);

  304.         hrc = CreateIoCompletionPort((HANDLE)buf->sclient, CompPort, (ULONG_PTR)clientobj, 0);
  305.         if (hrc == NULL) {
  306.             fprintf(stderr, "CompletionThread: CreateIoCompletionPort failed: %d\n", GetLastError());
  307.             return;
  308.         }

  309.         sendobj = GetBufferObjEx(BytesTransfered);
  310.         memcpy(sendobj->buf, buf->buf, BytesTransfered);

  311.         if (PostSend(clientobj, sendobj) == NO_ERROR)
  312.         {
  313.             // Now post some receives on this new connection
  314.             for(i = 0; i < gOverlappedCount; i++)
  315.             {
  316.                 recvobj = GetBufferObjEx(gBufferSize);

  317.                 if (PostRecv(clientobj, recvobj) != NO_ERROR)
  318.                 {
  319.                     FreeBufferObjEx(recvobj);
  320.                     error = SOCKET_ERROR;
  321.                     break;
  322.                 }
  323.             }
  324.         }
  325.         else
  326.         {
  327.             FreeBufferObjEx(sendobj);
  328.             error = SOCKET_ERROR;
  329.         }

  330.         PostAccept(sock, buf);

  331.         if (error != NO_ERROR)
  332.         {
  333.             if (clientobj->OutstandingOps == 0)
  334.             {
  335.                 closesocket(clientobj->s);
  336.                 clientobj->s = INVALID_SOCKET;
  337.                 FreeSocketObj(clientobj);
  338.             }
  339.             else
  340.             {
  341.                 clientobj->bClosing = TRUE;
  342.             }
  343.             error = NO_ERROR;
  344.         }

  345.     } else if ((buf->operation == OP_READ) && (error == NO_ERROR)) {
  346.         if ((BytesTransfered > 0))
  347.         {
  348.             printf("HandleIo: %d\n", handleNum++);
  349.             // Create a buffer to send
  350.             sendobj = GetBufferObjEx(gBufferSize);
  351.             printf("handlecut %d.\n", handlecut++);

  352.             // Swap the buffers (i.e. buffer we just received becomes the send buffer)
  353.             tmp = sendobj->buf;
  354.             sendobj->buflen = BytesTransfered;
  355.             sendobj->buf = buf->buf;
  356.             sendobj->IoOrder = buf->IoOrder;

  357.             buf->buf = tmp;
  358.             buf->buflen = gBufferSize;

  359.             InsertPendingSend(sock, sendobj);

  360.             if (DoSends(sock) != NO_ERROR)
  361.             {
  362.                 error = SOCKET_ERROR;
  363.                 printf("SOCKET_ERROR.\n");
  364.             }
  365.             else
  366.             {
  367.                 // Post another receive
  368.                 if (PostRecv(sock, buf) != NO_ERROR)
  369.                 {
  370.                     // In the event the recv fails, clean up the connection
  371.                     FreeBufferObjEx(buf);
  372.                     error = SOCKET_ERROR;
  373.                     printf("SOCKET_ERROR.\n");
  374.                 }
  375.             }
  376.         }
  377.         else
  378.         {
  379.             sock->bClosing = TRUE;

  380.             // Free the receive buffer
  381.             FreeBufferObjEx(buf);

  382.             if (DoSends(sock) != NO_ERROR)
  383.             {
  384.                 error = SOCKET_ERROR;
  385.                 printf("SOCKET_ERROR.\n");
  386.             }

  387.             // If this was the last outstanding operation on socket, clean it up
  388.             if ((sock->OutstandingOps == 0) && (sock->OutOfOrderSends.count == 0))
  389.             {
  390.                 bCleanupSocket = TRUE;
  391.             }
  392.         }
  393.     } else if (buf->operation == OP_WRITE) {
  394.         FreeBufferObjEx(buf);

  395.         if (DoSends(sock) != NO_ERROR)
  396.         {
  397.             error = SOCKET_ERROR;
  398.         }
  399.     }

  400.     if (error != NO_ERROR) {
  401.         sock->bClosing = TRUE;
  402.     }

  403.     if ((InterlockedDecrement(&sock->OutstandingOps) == 0) && (sock->bClosing) && (sock->OutOfOrderSends.count == 0) ) {
  404.         bCleanupSocket = TRUE;
  405.     } else {
  406.         if (DoSends(sock) != NO_ERROR) {
  407.             bCleanupSocket = TRUE;
  408.         }
  409.     }

  410.     LeaveCriticalSection(&sock->SockCritSec);

  411.     if (bCleanupSocket)
  412.     {
  413.         closesocket(sock->s);
  414.         sock->s = INVALID_SOCKET;

  415.         FreeSocketObj(sock);
  416.     }

  417. }

  418. int iocpNum = 0;

  419. DWORD WINAPI CompletionThread(LPVOID lpParam) {
  420.     SOCKET_OBJ *sockobj=NULL; // Per socket object for completed I/O
  421.     BUFFER_OBJ_EX *bufobj=NULL; // Per I/O object for completed I/O
  422.     OVERLAPPED *lpOverlapped=NULL; // Pointer to overlapped structure for completed I/O
  423.     HANDLE CompletionPort; // Completion port handle
  424.     DWORD BytesTransfered, // Number of bytes transfered
  425.                     Flags; // Flags for completed I/O
  426.     int rc,
  427.                     error;

  428.     CompletionPort = (HANDLE)lpParam;
  429.     while (true) {
  430.         error = NO_ERROR;
  431.         rc = GetQueuedCompletionStatus(CompletionPort, &BytesTransfered, (PULONG_PTR)&sockobj, &lpOverlapped, INFINITE);
  432.         printf("iocp %d.\n", iocpNum++);
  433.         bufobj = CONTAINING_RECORD(lpOverlapped, BUFFER_OBJ_EX, ol);

  434.         if (rc == FALSE)
  435.         {
  436.             printf("false.\n");
  437.             rc = WSAGetOverlappedResult(sockobj->s, &bufobj->ol, &BytesTransfered, FALSE, &Flags);
  438.             if (rc == FALSE)
  439.             {
  440.                 error = WSAGetLastError();
  441.                 printf("WSAGetOverlappedResult failed %d.\n", error);
  442.             }
  443.         }

  444.         HandleIo(sockobj, bufobj, CompletionPort, BytesTransfered, error);
  445.     }

  446.     ExitProcess(0);
  447.     return 0;
  448. }

  449. int _tmain(int argc, _TCHAR* argv[])
  450. {
  451.     WSADATA wsd;
  452.     SYSTEM_INFO sysinfo;
  453.     SOCKET_OBJ *sockobj=NULL;
  454.     SocketObjHeader ListenSockets;
  455.     HANDLE CompletionPort,
  456.                      CompThreads[MAX_COMPLETION_THREAD_COUNT],
  457.                      hrc;
  458.     int endpointcount=0,
  459.                      interval,
  460.                      rc,
  461.                      i;
  462.     struct addrinfo *res=NULL,
  463.                     *ptr=NULL;

  464.     if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
  465.     {
  466.         fprintf(stderr, "unable to load Winsock!\n");
  467.         return -1;
  468.     }

  469.     CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
  470.     if (CompletionPort == NULL) {
  471.         fprintf(stderr, "CreateIoCompletionPort failed.\n");
  472.         return 0;
  473.     }

  474.     GetSystemInfo(&sysinfo);
  475.     if (sysinfo.dwNumberOfProcessors > MAX_COMPLETION_THREAD_COUNT) {
  476.         sysinfo.dwNumberOfProcessors = MAX_COMPLETION_THREAD_COUNT;
  477.     }
  478.     
  479.     //for (i = 0; i < sysinfo.dwNumberOfProcessors; ++i) {
  480.     for (i = 0; i < 1; ++i) {
  481.         CompThreads[i] = CreateThread(NULL, 0, CompletionThread, (LPVOID)CompletionPort, 0, NULL);
  482.         if (CompThreads[i] == NULL) {
  483.             fprintf(stderr, "CreateThread failed.\n");
  484.             return -1;
  485.         }
  486.     }

  487.     res = ResolveAddress(gSrvAddr, gPort, gAddressFamily, gSocketType, gProtocol);
  488.     if (res == NULL)
  489.     {
  490.         fprintf(stderr, "ResolveAddress failed to return any addresses!\n");
  491.         return -1;
  492.     }

  493.     InitializeSingleHead(&ListenSockets);

  494.     ptr = res;
  495.     while (ptr) {
  496.         sockobj = GetSocketObj(INVALID_SOCKET, ptr->ai_family);

  497.         sockobj->s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  498.         if (sockobj->s == INVALID_SOCKET)
  499.         {
  500.             fprintf(stderr,"socket failed: %d\n", WSAGetLastError());
  501.             return -1;
  502.         }

  503.         hrc = CreateIoCompletionPort((HANDLE)sockobj->s, CompletionPort, (ULONG_PTR)sockobj, 0);
  504.         if (hrc == NULL)
  505.         {
  506.             fprintf(stderr, "CreateIoCompletionPort failed: %d\n", GetLastError());
  507.             return -1;
  508.         }

  509.         rc = bind(sockobj->s, ptr->ai_addr, ptr->ai_addrlen);
  510.         if (rc == SOCKET_ERROR) {
  511.             fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
  512.             return -1;
  513.         }

  514.         if (gProtocol == IPPROTO_TCP) {
  515.             BUFFER_OBJ_EX *acceptobj=NULL;
  516.             GUID guidAcceptEx = WSAID_ACCEPTEX,
  517.                             guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
  518.             DWORD bytes;

  519.             // Need to load the Winsock extension functions from each provider
  520.             // -- e.g. AF_INET and AF_INET6.
  521.             rc = WSAIoctl(sockobj->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, sizeof(guidAcceptEx),
  522.                    &sockobj->lpfnAcceptEx, sizeof(sockobj->lpfnAcceptEx), &bytes, NULL, NULL);
  523.             if (rc == SOCKET_ERROR)
  524.             {
  525.                 fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n",
  526.                         WSAGetLastError());
  527.                 return -1;
  528.             }

  529.             rc = WSAIoctl(sockobj->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidGetAcceptExSockaddrs, sizeof(guidGetAcceptExSockaddrs),
  530.                    &sockobj->lpfnGetAcceptExSockaddrs, sizeof(sockobj->lpfnGetAcceptExSockaddrs), &bytes, NULL, NULL);
  531.             if (rc == SOCKET_ERROR)
  532.             {
  533.                 fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER faled: %d\n",
  534.                         WSAGetLastError());
  535.                 return -1;
  536.             }

  537.             rc = listen(sockobj->s, 100);
  538.             if (rc == SOCKET_ERROR) {
  539.                 fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
  540.                 return -1;
  541.             }

  542.             sockobj->PendingAccepts = (BUFFER_OBJ_EX **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(BUFFER_OBJ_EX *) * gOverlappedCount));
  543.             if (sockobj->PendingAccepts == NULL)
  544.             {
  545.                 fprintf(stderr, "HeapAlloc failed: %d\n", GetLastError());
  546.                 ExitProcess(-1);
  547.             }

  548.             for(i=0; i < gOverlappedCount ;i++)
  549.             {
  550.                 sockobj->PendingAccepts[i] = acceptobj = GetBufferObjEx(gBufferSize);
  551.                 PostAccept(sockobj, acceptobj);
  552.             }

  553.             EnqueueSingleList(&ListenSockets, &(sockobj->next));
  554.         }

  555.         ptr = ptr->ai_next;
  556.     }

  557.     freeaddrinfo(res);

  558.     interval = 0;
  559.     while (true) {
  560.         rc = WSAWaitForMultipleEvents(1, CompThreads, TRUE, 5000, FALSE);
  561.         if (rc == WAIT_FAILED) {
  562.             fprintf(stderr, "WSAWaitForMultipleEvents failed: %d\n", WSAGetLastError());
  563.             break;
  564.         } else if (rc == WAIT_TIMEOUT) {
  565.             interval++;

  566.             if (interval == 12) {
  567.                 SocketObj *listenptr=NULL;
  568.                 int optval,
  569.                              optlen;

  570.                 // Walk the list of outstanding accepts
  571.                 listenptr = (SocketObj *)GotoNextSingleList(&ListenSockets, ListenSockets.head);
  572.                 while (listenptr)
  573.                 {
  574.                     sockobj = (SOCKET_OBJ *)container_of(SOCKET_OBJ, next, listenptr);
  575.                     for(i=0; i < gOverlappedCount ;i++)
  576.                     {
  577.                         optlen = sizeof(optval);
  578.                         rc = getsockopt(
  579.                                 sockobj->PendingAccepts[i]->sclient,
  580.                                 SOL_SOCKET,
  581.                                 SO_CONNECT_TIME,
  582.                                 (char *)&optval,
  583.                              &optlen
  584.                              );
  585.                         if (rc == SOCKET_ERROR)
  586.                         {
  587.                             fprintf(stderr, "getsockopt: SO_CONNECT_TIME failed: %d\n", WSAGetLastError());
  588.                             return -1;
  589.                         }
  590.                         if ((optval != 0xFFFFFFFF) && (optval > 300))
  591.                         {
  592.                             closesocket(sockobj->PendingAccepts[i]->sclient);
  593.                         }
  594.                     }
  595.                     listenptr = (SocketObj *)GotoNextSingleList(&ListenSockets, listenptr);
  596.                 }
  597.                 interval = 0;
  598.             }
  599.         }
  600.     }

  601.     WSACleanup();

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