Windows Socket I/O模型之 I/O完成端口

  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. }

版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。

猜你喜欢

转载自blog.csdn.net/micklongen/article/details/6171929