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

  1. # include < winsock2. h>
  2. # include < ws2tcpip. h>
  3. # include < mswsock. h>
  4. # include < windows. h>
  5.  
  6. # include "resolve.h"
  7. # include "public.h"
  8.  
  9. # define DEFAULT_OVERLAPPED_COUNT 5
  10. # define MAX_COMPLETION_THREAD_COUNT 32 // Maximum number of completion threads allowed
  11.  
  12. typedef SINGLE_LIST_HEADER SocketObjHeader;
  13. typedef SINGLE_LIST SocketObj;
  14. typedef DOUBLE_LIST_HEADER BufferObjHeader;
  15. typedef DOUBLE_LIST BufferObj;
  16.  
  17. int gOverlappedCount = DEFAULT_OVERLAPPED_COUNT;
  18.  
  19. typedef struct _BUFFER_OBJ_EX {
  20.     WSAOVERLAPPED ol; // Overlapped structure
  21.  
  22.     SOCKET sclient; // Used for AcceptEx client socket
  23.  
  24.     char * buf; // Buffer for send/recv/AcceptEx
  25.     int buflen; // Length of the buffer
  26.  
  27.     int operation; // Type of operation submitted
  28. # define OP_ACCEPT 0 // AcceptEx
  29. # define OP_READ 1 // WSARecv/WSARecvFrom
  30. # define OP_WRITE 2 // WSASend?WSASendTo
  31.  
  32.     SOCKADDR_STORAGE addr; // Remote address (UDP)
  33.     int addrlen; // Remote address length
  34.  
  35.     ULONG IoOrder; // Order in which this I/O was posted
  36.  
  37.     BufferObj bufDList;
  38. } BUFFER_OBJ_EX;
  39.  
  40. typedef struct _SOCKET_OBJ
  41. {
  42.     SOCKET s; // Socket handle for client connection
  43.  
  44.     int af, // Address family of socket (AF_INET or AF_INET6)
  45.                          bClosing; // Indicates socket is closing
  46.  
  47.     volatile LONG OutstandingOps; // Number of outstanding overlapped ops
  48.  
  49.     BUFFER_OBJ_EX * * PendingAccepts; // Array of pending AcceptEx calls (listening socket only)
  50.  
  51.     ULONG LastSendIssued, // Last sequence number sent
  52.                          IoCountIssued; // Next sequence number assigned to receives
  53.     BufferObjHeader OutOfOrderSends; // List of send buffers that completed out of order
  54.  
  55.     // Pointers to Microsoft specific extensions (listening socket only)
  56.     LPFN_ACCEPTEX lpfnAcceptEx;
  57.     LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs;
  58.  
  59.     CRITICAL_SECTION SockCritSec; // Synchronize access to this SOCKET_OBJ
  60.  
  61.     SocketObj next; // Used to chain SOCKET_OBJ together
  62. } SOCKET_OBJ;
  63.  
  64. SOCKET_OBJ * GetSocketObj( SOCKET s, int af)
  65. {
  66.     SOCKET_OBJ * sockobj= NULL ;
  67.  
  68.     sockobj = ( SOCKET_OBJ * ) HeapAlloc( GetProcessHeap( ) , HEAP_ZERO_MEMORY, sizeof ( SOCKET_OBJ) ) ;
  69.     if ( sockobj = = NULL )
  70.     {
  71.         fprintf ( stderr , "GetSocketObj: HeapAlloc failed: %d/n" , GetLastError( ) ) ;
  72.         ExitProcess( - 1) ;
  73.     }
  74.  
  75.     InitializeCriticalSection( & sockobj- > SockCritSec) ;
  76.     InitializeDoubleHead( & sockobj- > OutOfOrderSends) ;
  77.  
  78.     sockobj- > IoCountIssued = ( ( gProtocol = = IPPROTO_TCP ) ? 1 : 0) ;
  79.  
  80.     // Initialize the members
  81.     sockobj- > s = s;
  82.     sockobj- > af = af;
  83.  
  84.     return sockobj;
  85. }
  86.  
  87. BUFFER_OBJ_EX * GetBufferObjEx( int buflen)
  88. {
  89.     BUFFER_OBJ_EX * newobj= NULL ;
  90.  
  91.     // Allocate the object
  92.     newobj = ( BUFFER_OBJ_EX * ) HeapAlloc( GetProcessHeap( ) , HEAP_ZERO_MEMORY, sizeof ( BUFFER_OBJ_EX) ) ;
  93.     if ( newobj = = NULL ) {
  94.         printf ( "GetBufferObj: HeapAlloc failed: %d/n" , GetLastError( ) ) ;
  95.         ExitProcess( - 1) ;
  96.     }
  97.  
  98.     // Allocate the buffer
  99.     newobj- > buf = ( char * ) HeapAlloc( GetProcessHeap( ) , HEAP_ZERO_MEMORY, sizeof ( BYTE) * buflen) ;
  100.     if ( newobj- > buf = = NULL ) {
  101.         printf ( "GetBufferObj: HeapAlloc failed: %d/n" , GetLastError( ) ) ;
  102.         ExitProcess( - 1) ;
  103.     }
  104.  
  105.     newobj- > buflen = buflen;
  106.     newobj- > addrlen = sizeof ( newobj- > addr) ;
  107.  
  108.     return newobj;
  109. }
  110.  
  111. void FreeBufferObjEx( BUFFER_OBJ_EX * obj)
  112. {
  113.     HeapFree( GetProcessHeap( ) , 0, obj- > buf) ;
  114.     HeapFree( GetProcessHeap( ) , 0, obj) ;
  115. }
  116.  
  117. void FreeSocketObj( SOCKET_OBJ * obj)
  118. {
  119.     BUFFER_OBJ_EX * ptr= NULL ,
  120.                 * tmp= NULL ;
  121.  
  122.     if ( obj- > OutstandingOps ! = 0)
  123.     {
  124.         // Still outstanding operations so just return
  125.         return ;
  126.     }
  127.     // Close the socket if it hasn't already been closed
  128.     if ( obj- > s ! = INVALID_SOCKET)
  129.     {
  130.         closesocket( obj- > s) ;
  131.         obj- > s = INVALID_SOCKET;
  132.     }
  133.  
  134.     DeleteCriticalSection( & obj- > SockCritSec) ;
  135.  
  136.     HeapFree( GetProcessHeap( ) , 0, obj) ;
  137. }
  138.  
  139. void InsertPendingSend( SOCKET_OBJ * sock, BUFFER_OBJ_EX * send )
  140. {
  141.     BufferObj * ptr = NULL ;
  142.     BUFFER_OBJ_EX * obj = NULL ;
  143.  
  144.     EnterCriticalSection( & sock- > SockCritSec) ;
  145.  
  146.     ptr = ( BufferObj * ) GotoNextDoubleList( & sock- > OutOfOrderSends, & sock- > OutOfOrderSends. head) ;
  147.     while ( ptr)
  148.     {
  149.         obj = ( BUFFER_OBJ_EX * ) container_of( BUFFER_OBJ_EX, bufDList, ptr) ;
  150.         if ( send - > IoOrder < obj- > IoOrder)
  151.         {
  152.             break ;
  153.         }
  154.  
  155.         ptr = ( BufferObj * ) GotoNextDoubleList( & sock- > OutOfOrderSends, ptr) ;
  156.     }
  157.     if ( ptr = = NULL )
  158.         ptr = & sock- > OutOfOrderSends. head;
  159.  
  160.     EnqueueDoubleListBefore( & sock- > OutOfOrderSends, ptr, & send - > bufDList) ;
  161.  
  162.     LeaveCriticalSection( & sock- > SockCritSec) ;
  163. }
  164.  
  165. int PostRecv( SOCKET_OBJ * sock, BUFFER_OBJ_EX * recvobj)
  166. {
  167.     WSABUF wbuf;
  168.     DWORD bytes,
  169.             flags;
  170.     int rc;
  171.  
  172.  
  173.     recvobj- > operation = OP_READ;
  174.  
  175.     wbuf. buf = recvobj- > buf;
  176.     wbuf. len = recvobj- > buflen;
  177.  
  178.     flags = 0;
  179.  
  180.     EnterCriticalSection( & sock- > SockCritSec) ;
  181.  
  182.     // Assign the IO order to this receive. This must be performned within
  183.     // the critical section. The operation of assigning the IO count and posting
  184.     // the receive cannot be interupted.
  185.     recvobj- > IoOrder = sock- > IoCountIssued;
  186.     sock- > IoCountIssued+ + ;
  187.  
  188.     if ( gProtocol = = IPPROTO_TCP )
  189.     {
  190.         rc = WSARecv(
  191.                 sock- > s,
  192.                & wbuf,
  193.                 1,
  194.                & bytes,
  195.                & flags,
  196.                & recvobj- > ol,
  197.                 NULL
  198.                 ) ;
  199.     }
  200.     else
  201.     {
  202.         ExitProcess( - 1) ;
  203.     }
  204.  
  205.     LeaveCriticalSection( & sock- > SockCritSec) ;
  206.  
  207.     if ( rc = = SOCKET_ERROR)
  208.     {
  209.         if ( WSAGetLastError( ) ! = WSA_IO_PENDING)
  210.         {
  211.             fprintf ( stderr , "PostRecv: WSARecv* failed: %d/n" , WSAGetLastError( ) ) ;
  212.             return SOCKET_ERROR;
  213.         }
  214.     }
  215.  
  216.     // Increment outstanding overlapped operations
  217.     InterlockedIncrement( & sock- > OutstandingOps) ;
  218.  
  219.     return NO_ERROR;
  220. }
  221.  
  222. int sendnum = 0;
  223.  
  224. int PostSend( SOCKET_OBJ * sock, BUFFER_OBJ_EX * sendobj)
  225. {
  226.     WSABUF wbuf;
  227.     DWORD bytes;
  228.     int rc;
  229.  
  230.     sendobj- > operation = OP_WRITE;
  231.  
  232.     wbuf. buf = sendobj- > buf;
  233.     wbuf. len = sendobj- > buflen;
  234.  
  235.     EnterCriticalSection( & sock- > SockCritSec) ;
  236.  
  237.     // Incrmenting the last send issued and issuing the send should not be
  238.     // interuptable.
  239.     sock- > LastSendIssued+ + ;
  240.  
  241.     if ( gProtocol = = IPPROTO_TCP )
  242.     {
  243.         printf ( "send %d/n" , sendnum+ + ) ;
  244.         rc = WSASend(
  245.                 sock- > s,
  246.                & wbuf,
  247.                 1,
  248.                & bytes,
  249.                 0,
  250.                & sendobj- > ol,
  251.                 NULL
  252.                 ) ;
  253.     }
  254.     else {
  255.         ExitProcess( - 1) ;
  256.     }
  257.  
  258.     LeaveCriticalSection( & sock- > SockCritSec) ;
  259.  
  260.     if ( rc = = SOCKET_ERROR)
  261.     {
  262.         if ( WSAGetLastError( ) ! = WSA_IO_PENDING)
  263.         {
  264.             fprintf ( stderr , "PostSend: WSASend* failed: %d/n" , WSAGetLastError( ) ) ;
  265.             return SOCKET_ERROR;
  266.         }
  267.     }
  268.  
  269.     // Increment the outstanding operation count
  270.     InterlockedIncrement( & sock- > OutstandingOps) ;
  271.  
  272.     return NO_ERROR;
  273. }
  274.  
  275. int PostAccept( SOCKET_OBJ * sock, BUFFER_OBJ_EX * acceptobj)
  276. {
  277.     DWORD bytes;
  278.     int rc;
  279.  
  280.     acceptobj- > operation = OP_ACCEPT;
  281.  
  282.     // Create the client socket for an incoming connection
  283.     acceptobj- > sclient = socket ( sock- > af, SOCK_STREAM , IPPROTO_TCP ) ;
  284.     if ( acceptobj- > sclient = = INVALID_SOCKET)
  285.     {
  286.         fprintf ( stderr , "PostAccept: socket failed: %d/n" , WSAGetLastError( ) ) ;
  287.         return - 1;
  288.     }
  289.  
  290.     rc = sock- > lpfnAcceptEx(
  291.             sock- > s,
  292.             acceptobj- > sclient,
  293.             acceptobj- > buf,
  294.             acceptobj- > buflen - ( ( sizeof ( SOCKADDR_STORAGE) + 16) * 2) ,
  295.             sizeof ( SOCKADDR_STORAGE) + 16,
  296.             sizeof ( SOCKADDR_STORAGE) + 16,
  297.            & bytes,
  298.            & acceptobj- > ol
  299.             ) ;
  300.     if ( rc = = FALSE )
  301.     {
  302.         if ( WSAGetLastError( ) ! = WSA_IO_PENDING)
  303.         {
  304.             fprintf ( stderr , "PostAccept: AcceptEx failed: %d/n" , WSAGetLastError( ) ) ;
  305.             return SOCKET_ERROR;
  306.         }
  307.     }
  308.  
  309.     // Increment the outstanding overlapped count for this socket
  310.     InterlockedIncrement( & sock- > OutstandingOps) ;
  311.  
  312.     return NO_ERROR;
  313. }
  314.  
  315. int DoSends( SOCKET_OBJ * sock)
  316. {
  317.     BufferObj * ptr = NULL ;
  318.     BufferObj * tmp = NULL ;
  319.     BUFFER_OBJ_EX * sendobj = NULL ;
  320.  
  321.     int ret;
  322.  
  323.     ret = NO_ERROR;
  324.  
  325.     EnterCriticalSection( & sock- > SockCritSec) ;
  326.  
  327.     ptr = ( BufferObj * ) GotoNextDoubleList( & sock- > OutOfOrderSends, & sock- > OutOfOrderSends. head) ;
  328.     while ( ptr) {
  329.         sendobj = ( BUFFER_OBJ_EX * ) container_of( BUFFER_OBJ_EX, bufDList, ptr) ;
  330.         if ( ( sendobj) & & ( sendobj- > IoOrder = = sock- > LastSendIssued) )
  331.         {
  332.             if ( PostSend( sock, sendobj) ! = NO_ERROR)
  333.             {
  334.                 FreeBufferObjEx( sendobj) ;
  335.     
  336.                 ret = SOCKET_ERROR;
  337.                 break ;
  338.             }
  339.         } else
  340.             break ;
  341.         tmp = ptr;
  342.         ptr = ( BufferObj * ) GotoNextDoubleList( & sock- > OutOfOrderSends, ptr) ;
  343.  
  344.         RemoveDoubleList( & sock- > OutOfOrderSends, tmp) ;
  345.         //FreeBufferObjEx(sendobj);
  346.     }
  347.  
  348.     LeaveCriticalSection( & sock- > SockCritSec) ;
  349.  
  350.     return ret;
  351. }
  352.  
  353. int handleNum = 0;
  354. int handlecut = 0;
  355.  
  356. void HandleIo( SOCKET_OBJ * sock, BUFFER_OBJ_EX * buf, HANDLE CompPort, DWORD BytesTransfered, DWORD error ) {
  357.     SOCKET_OBJ * clientobj= NULL ; // New client object for accepted connections
  358.     BUFFER_OBJ_EX * recvobj= NULL , // Used to post new receives on accepted connections
  359.                * sendobj= NULL ; // Used to post new sends for data received
  360.     BOOL bCleanupSocket;
  361.     char * tmp;
  362.     int i;
  363.  
  364.     bCleanupSocket = FALSE ;
  365.  
  366.     if ( ( error ! = NO_ERROR) & & ( gProtocol = = IPPROTO_TCP ) ) {
  367.         FreeBufferObjEx( buf) ;
  368.  
  369.         if ( InterlockedDecrement( & sock- > OutstandingOps) = = 0) {
  370.             FreeSocketObj( sock) ;
  371.         }
  372.         return ;
  373.     }
  374.  
  375.     EnterCriticalSection( & sock- > SockCritSec) ;
  376.  
  377.     if ( buf- > operation = = OP_ACCEPT) {
  378.         HANDLE hrc;
  379.         SOCKADDR_STORAGE * LocalSockaddr= NULL ,
  380.                          * RemoteSockaddr= NULL ;
  381.         int LocalSockaddrLen,
  382.                           RemoteSockaddrLen;
  383.  
  384.         sock- > lpfnGetAcceptExSockaddrs(
  385.                 buf- > buf, buf- > buflen - ( ( sizeof ( SOCKADDR_STORAGE) + 16) * 2) ,
  386.                 sizeof ( SOCKADDR_STORAGE) + 16, sizeof ( SOCKADDR_STORAGE) + 16,
  387.                 ( SOCKADDR * * ) & LocalSockaddr, & LocalSockaddrLen,
  388.                 ( SOCKADDR * * ) & RemoteSockaddr, & RemoteSockaddrLen) ;
  389.  
  390.         clientobj = GetSocketObj( buf- > sclient, sock- > af) ;
  391.  
  392.         hrc = CreateIoCompletionPort( ( HANDLE) buf- > sclient, CompPort, ( ULONG_PTR) clientobj, 0) ;
  393.         if ( hrc = = NULL ) {
  394.             fprintf ( stderr , "CompletionThread: CreateIoCompletionPort failed: %d/n" , GetLastError( ) ) ;
  395.             return ;
  396.         }
  397.  
  398.         sendobj = GetBufferObjEx( BytesTransfered) ;
  399.         memcpy ( sendobj- > buf, buf- > buf, BytesTransfered) ;
  400.  
  401.         if ( PostSend( clientobj, sendobj) = = NO_ERROR)
  402.         {
  403.             // Now post some receives on this new connection
  404.             for ( i = 0; i < gOverlappedCount; i+ + )
  405.             {
  406.                 recvobj = GetBufferObjEx( gBufferSize) ;
  407.  
  408.                 if ( PostRecv( clientobj, recvobj) ! = NO_ERROR)
  409.                 {
  410.                     FreeBufferObjEx( recvobj) ;
  411.                     error = SOCKET_ERROR;
  412.                     break ;
  413.                 }
  414.             }
  415.         }
  416.         else
  417.         {
  418.             FreeBufferObjEx( sendobj) ;
  419.             error = SOCKET_ERROR;
  420.         }
  421.  
  422.         PostAccept( sock, buf) ;
  423.  
  424.         if ( error ! = NO_ERROR)
  425.         {
  426.             if ( clientobj- > OutstandingOps = = 0)
  427.             {
  428.                 closesocket( clientobj- > s) ;
  429.                 clientobj- > s = INVALID_SOCKET;
  430.                 FreeSocketObj( clientobj) ;
  431.             }
  432.             else
  433.             {
  434.                 clientobj- > bClosing = TRUE ;
  435.             }
  436.             error = NO_ERROR;
  437.         }
  438.  
  439.     } else if ( ( buf- > operation = = OP_READ) & & ( error = = NO_ERROR) ) {
  440.         if ( ( BytesTransfered > 0) )
  441.         {
  442.             printf ( "HandleIo: %d/n" , handleNum+ + ) ;
  443.             // Create a buffer to send
  444.             sendobj = GetBufferObjEx( gBufferSize) ;
  445.             printf ( "handlecut %d./n" , handlecut+ + ) ;
  446.  
  447.             // Swap the buffers (i.e. buffer we just received becomes the send buffer)
  448.             tmp = sendobj- > buf;
  449.             sendobj- > buflen = BytesTransfered;
  450.             sendobj- > buf = buf- > buf;
  451.             sendobj- > IoOrder = buf- > IoOrder;
  452.  
  453.             buf- > buf = tmp;
  454.             buf- > buflen = gBufferSize;
  455.  
  456.             InsertPendingSend( sock, sendobj) ;
  457.  
  458.             if ( DoSends( sock) ! = NO_ERROR)
  459.             {
  460.                 error = SOCKET_ERROR;
  461.                 printf ( "SOCKET_ERROR./n" ) ;
  462.             }
  463.             else
  464.             {
  465.                 // Post another receive
  466.                 if ( PostRecv( sock, buf) ! = NO_ERROR)
  467.                 {
  468.                     // In the event the recv fails, clean up the connection
  469.                     FreeBufferObjEx( buf) ;
  470.                     error = SOCKET_ERROR;
  471.                     printf ( "SOCKET_ERROR./n" ) ;
  472.                 }
  473.             }
  474.         }
  475.         else
  476.         {
  477.             sock- > bClosing = TRUE ;
  478.  
  479.             // Free the receive buffer
  480.             FreeBufferObjEx( buf) ;
  481.  
  482.             if ( DoSends( sock) ! = NO_ERROR)
  483.             {
  484.                 error = SOCKET_ERROR;
  485.                 printf ( "SOCKET_ERROR./n" ) ;
  486.             }
  487.  
  488.             // If this was the last outstanding operation on socket, clean it up
  489.             if ( ( sock- > OutstandingOps = = 0) & & ( sock- > OutOfOrderSends. count = = 0) )
  490.             {
  491.                 bCleanupSocket = TRUE ;
  492.             }
  493.         }
  494.     } else if ( buf- > operation = = OP_WRITE) {
  495.         FreeBufferObjEx( buf) ;
  496.  
  497.         if ( DoSends( sock) ! = NO_ERROR)
  498.         {
  499.             error = SOCKET_ERROR;
  500.         }
  501.     }
  502.  
  503.     if ( error ! = NO_ERROR) {
  504.         sock- > bClosing = TRUE ;
  505.     }
  506.  
  507.     if ( ( InterlockedDecrement( & sock- > OutstandingOps) = = 0) & & ( sock- > bClosing) & & ( sock- > OutOfOrderSends. count = = 0) ) {
  508.         bCleanupSocket = TRUE ;
  509.     } else {
  510.         if ( DoSends( sock) ! = NO_ERROR) {
  511.             bCleanupSocket = TRUE ;
  512.         }
  513.     }
  514.  
  515.     LeaveCriticalSection( & sock- > SockCritSec) ;
  516.  
  517.     if ( bCleanupSocket)
  518.     {
  519.         closesocket( sock- > s) ;
  520.         sock- > s = INVALID_SOCKET;
  521.  
  522.         FreeSocketObj( sock) ;
  523.     }
  524.  
  525. }
  526.  
  527. int iocpNum = 0;
  528.  
  529. DWORD WINAPI CompletionThread( LPVOID lpParam) {
  530.     SOCKET_OBJ * sockobj= NULL ; // Per socket object for completed I/O
  531.     BUFFER_OBJ_EX * bufobj= NULL ; // Per I/O object for completed I/O
  532.     OVERLAPPED * lpOverlapped= NULL ; // Pointer to overlapped structure for completed I/O
  533.     HANDLE CompletionPort; // Completion port handle
  534.     DWORD BytesTransfered, // Number of bytes transfered
  535.                     Flags; // Flags for completed I/O
  536.     int rc,
  537.                     error ;
  538.  
  539.     CompletionPort = ( HANDLE) lpParam;
  540.     while ( true ) {
  541.         error = NO_ERROR;
  542.         rc = GetQueuedCompletionStatus( CompletionPort, & BytesTransfered, ( PULONG_PTR) & sockobj, & lpOverlapped, INFINITE) ;
  543.         printf ( "iocp %d./n" , iocpNum+ + ) ;
  544.         bufobj = CONTAINING_RECORD( lpOverlapped, BUFFER_OBJ_EX, ol) ;
  545.  
  546.         if ( rc = = FALSE )
  547.         {
  548.             printf ( "false./n" ) ;
  549.             rc = WSAGetOverlappedResult( sockobj- > s, & bufobj- > ol, & BytesTransfered, FALSE , & Flags) ;
  550.             if ( rc = = FALSE )
  551.             {
  552.                 error = WSAGetLastError( ) ;
  553.                 printf ( "WSAGetOverlappedResult failed %d./n" , error ) ;
  554.             }
  555.         }
  556.  
  557.         HandleIo( sockobj, bufobj, CompletionPort, BytesTransfered, error ) ;
  558.     }
  559.  
  560.     ExitProcess( 0) ;
  561.     return 0;
  562. }
  563.  
  564. int _tmain( int argc, _TCHAR* argv[ ] )
  565. {
  566.     WSADATA wsd;
  567.     SYSTEM_INFO sysinfo;
  568.     SOCKET_OBJ * sockobj= NULL ;
  569.     SocketObjHeader ListenSockets;
  570.     HANDLE CompletionPort,
  571.                      CompThreads[ MAX_COMPLETION_THREAD_COUNT] ,
  572.                      hrc;
  573.     int endpointcount= 0,
  574.                      interval,
  575.                      rc,
  576.                      i;
  577.     struct addrinfo * res= NULL ,
  578.                     * ptr= NULL ;
  579.  
  580.     if ( WSAStartup( MAKEWORD( 2, 2) , & wsd) ! = 0)
  581.     {
  582.         fprintf ( stderr , "unable to load Winsock!/n" ) ;
  583.         return - 1;
  584.     }
  585.  
  586.     CompletionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL , NULL , 0) ;
  587.     if ( CompletionPort = = NULL ) {
  588.         fprintf ( stderr , "CreateIoCompletionPort failed./n" ) ;
  589.         return 0;
  590.     }
  591.  
  592.     GetSystemInfo( & sysinfo) ;
  593.     if ( sysinfo. dwNumberOfProcessors > MAX_COMPLETION_THREAD_COUNT) {
  594.         sysinfo. dwNumberOfProcessors = MAX_COMPLETION_THREAD_COUNT;
  595.     }
  596.     
  597.     //for (i = 0; i < sysinfo.dwNumberOfProcessors; ++i) {
  598.     for ( i = 0; i < 1; + + i) {
  599.         CompThreads[ i] = CreateThread( NULL , 0, CompletionThread, ( LPVOID) CompletionPort, 0, NULL ) ;
  600.         if ( CompThreads[ i] = = NULL ) {
  601.             fprintf ( stderr , "CreateThread failed./n" ) ;
  602.             return - 1;
  603.         }
  604.     }
  605.  
  606.     res = ResolveAddress( gSrvAddr, gPort, gAddressFamily, gSocketType, gProtocol) ;
  607.     if ( res = = NULL )
  608.     {
  609.         fprintf ( stderr , "ResolveAddress failed to return any addresses!/n" ) ;
  610.         return - 1;
  611.     }
  612.  
  613.     InitializeSingleHead( & ListenSockets) ;
  614.  
  615.     ptr = res;
  616.     while ( ptr) {
  617.         sockobj = GetSocketObj( INVALID_SOCKET, ptr- > ai_family) ;
  618.  
  619.         sockobj- > s = socket ( ptr- > ai_family, ptr- > ai_socktype, ptr- > ai_protocol) ;
  620.         if ( sockobj- > s = = INVALID_SOCKET)
  621.         {
  622.             fprintf ( stderr , "socket failed: %d/n" , WSAGetLastError( ) ) ;
  623.             return - 1;
  624.         }
  625.  
  626.         hrc = CreateIoCompletionPort( ( HANDLE) sockobj- > s, CompletionPort, ( ULONG_PTR) sockobj, 0) ;
  627.         if ( hrc = = NULL )
  628.         {
  629.             fprintf ( stderr , "CreateIoCompletionPort failed: %d/n" , GetLastError( ) ) ;
  630.             return - 1;
  631.         }
  632.  
  633.         rc = bind ( sockobj- > s, ptr- > ai_addr, ptr- > ai_addrlen) ;
  634.         if ( rc = = SOCKET_ERROR) {
  635.             fprintf ( stderr , "bind failed: %d/n" , WSAGetLastError( ) ) ;
  636.             return - 1;
  637.         }
  638.  
  639.         if ( gProtocol = = IPPROTO_TCP ) {
  640.             BUFFER_OBJ_EX * acceptobj= NULL ;
  641.             GUID guidAcceptEx = WSAID_ACCEPTEX,
  642.                             guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
  643.             DWORD bytes;
  644.  
  645.             // Need to load the Winsock extension functions from each provider
  646.             // -- e.g. AF_INET and AF_INET6.
  647.             rc = WSAIoctl( sockobj- > s, SIO_GET_EXTENSION_FUNCTION_POINTER, & guidAcceptEx, sizeof ( guidAcceptEx) ,
  648.                    & sockobj- > lpfnAcceptEx, sizeof ( sockobj- > lpfnAcceptEx) , & bytes, NULL , NULL ) ;
  649.             if ( rc = = SOCKET_ERROR)
  650.             {
  651.                 fprintf ( stderr , "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d/n" ,
  652.                         WSAGetLastError( ) ) ;
  653.                 return - 1;
  654.             }
  655.  
  656.             rc = WSAIoctl( sockobj- > s, SIO_GET_EXTENSION_FUNCTION_POINTER, & guidGetAcceptExSockaddrs, sizeof ( guidGetAcceptExSockaddrs) ,
  657.                    & sockobj- > lpfnGetAcceptExSockaddrs, sizeof ( sockobj- > lpfnGetAcceptExSockaddrs) , & bytes, NULL , NULL ) ;
  658.             if ( rc = = SOCKET_ERROR)
  659.             {
  660.                 fprintf ( stderr , "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER faled: %d/n" ,
  661.                         WSAGetLastError( ) ) ;
  662.                 return - 1;
  663.             }
  664.  
  665.             rc = listen ( sockobj- > s, 100) ;
  666.             if ( rc = = SOCKET_ERROR) {
  667.                 fprintf ( stderr , "listen failed: %d/n" , WSAGetLastError( ) ) ;
  668.                 return - 1;
  669.             }
  670.  
  671.             sockobj- > PendingAccepts = ( BUFFER_OBJ_EX * * ) HeapAlloc( GetProcessHeap( ) , HEAP_ZERO_MEMORY, ( sizeof ( BUFFER_OBJ_EX * ) * gOverlappedCount) ) ;
  672.             if ( sockobj- > PendingAccepts = = NULL )
  673.             {
  674.                 fprintf ( stderr , "HeapAlloc failed: %d/n" , GetLastError( ) ) ;
  675.                 ExitProcess( - 1) ;
  676.             }
  677.  
  678.             for ( i= 0; i < gOverlappedCount ; i+ + )
  679.             {
  680.                 sockobj- > PendingAccepts[ i] = acceptobj = GetBufferObjEx( gBufferSize) ;
  681.                 PostAccept( sockobj, acceptobj) ;
  682.             }
  683.  
  684.             EnqueueSingleList( & ListenSockets, & ( sockobj- > next) ) ;
  685.         }
  686.  
  687.         ptr = ptr- > ai_next;
  688.     }
  689.  
  690.     freeaddrinfo ( res) ;
  691.  
  692.     interval = 0;
  693.     while ( true ) {
  694.         rc = WSAWaitForMultipleEvents( 1, CompThreads, TRUE , 5000, FALSE ) ;
  695.         if ( rc = = WAIT_FAILED) {
  696.             fprintf ( stderr , "WSAWaitForMultipleEvents failed: %d/n" , WSAGetLastError( ) ) ;
  697.             break ;
  698.         } else if ( rc = = WAIT_TIMEOUT) {
  699.             interval+ + ;
  700.  
  701.             if ( interval = = 12) {
  702.                 SocketObj * listenptr= NULL ;
  703.                 int optval,
  704.                              optlen;
  705.  
  706.                 // Walk the list of outstanding accepts
  707.                 listenptr = ( SocketObj * ) GotoNextSingleList( & ListenSockets, ListenSockets. head) ;
  708.                 while ( listenptr)
  709.                 {
  710.                     sockobj = ( SOCKET_OBJ * ) container_of( SOCKET_OBJ, next, listenptr) ;
  711.                     for ( i= 0; i < gOverlappedCount ; i+ + )
  712.                     {
  713.                         optlen = sizeof ( optval) ;
  714.                         rc = getsockopt (
  715.                                 sockobj- > PendingAccepts[ i] - > sclient,
  716.                                 SOL_SOCKET,
  717.                                 SO_CONNECT_TIME,
  718.                                 ( char * ) & optval,
  719.                              & optlen
  720.                              ) ;
  721.                         if ( rc = = SOCKET_ERROR)
  722.                         {
  723.                             fprintf ( stderr , "getsockopt: SO_CONNECT_TIME failed: %d/n" , WSAGetLastError( ) ) ;
  724.                             return - 1;
  725.                         }
  726.                         if ( ( optval ! = 0xFFFFFFFF) & & ( optval > 300) )
  727.                         {
  728.                             closesocket( sockobj- > PendingAccepts[ i] - > sclient) ;
  729.                         }
  730.                     }
  731.                     listenptr = ( SocketObj * ) GotoNextSingleList( & ListenSockets, listenptr) ;
  732.                 }
  733.                 interval = 0;
  734.             }
  735.         }
  736.     }
  737.  
  738.     WSACleanup( ) ;
  739.  
  740.     return 0;
  741. }

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值