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

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

猜你喜欢

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