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

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值