# include < winsock2. h> # include < ws2tcpip
. h
># include < mswsock
. h
># include < windows
. h
> # include "resolve.h"# include "public.h" typedef SINGLE_LIST_HEADER SocketObjHeader
;typedef SINGLE_LIST SocketObj
;typedef SINGLE_LIST_HEADER ThreadObjHeader
;typedef SINGLE_LIST ThreadObj
;typedef DOUBLE_LIST_HEADER BufferObjHeader
;typedef DOUBLE_LIST BufferObj
; # define DEFAULT_OVERLAPPED_COUNT 5
struct _SOCKET_OBJ
;struct _THREAD_OBJ
; int gOverlappedCount
= DEFAULT_OVERLAPPED_COUNT
; typedef struct _BUFFER_OBJ_EX
{ WSAOVERLAPPED ol
; // Overlapped structure SOCKET sclient
; // Used for AcceptEx client socket char * buf
; // Buffer for send/recv/AcceptEx int buflen
; // Length of the buffer int operation
; // Type of operation submitted# define OP_ACCEPT 0
// AcceptEx# define OP_READ 1
// WSARecv/WSARecvFrom# define OP_WRITE 2
// WSASend?WSASendTo struct _SOCKET_OBJ
* Socket ; // SOCKET_OBJ that this I/O belongs to struct _THREAD_OBJ
* Thread
; // THREAD_OBJ this I/O is assigned to SOCKADDR_STORAGE addr
; // Remote address (UDP) int addrlen
; // Remote address length BufferObj bufDList
;} BUFFER_OBJ_EX
; typedef struct _SOCKET_OBJ
{ SOCKET s
; // Socket handle for client connection int af
, // Address family of socket (AF_INET or AF_INET6) bClosing
; // Indicates socket is closing volatile LONG OutstandingOps
; // Number of outstanding overlapped ops BUFFER_OBJ_EX
* * PendingAccepts
; // Array of pending AcceptEx calls (listening socket only) // Pointers to Microsoft specific extensions (listening socket only) LPFN_ACCEPTEX lpfnAcceptEx
; LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs
; CRITICAL_SECTION SockCritSec
; // Synchronize access to this SOCKET_OBJ SocketObj next
; // Used to chain SOCKET_OBJ together} SOCKET_OBJ
; typedef struct _THREAD_OBJ
{ DOUBLE_LIST_HEADER BufferList
; // Linked list of all sockets allocated int EventCount
; // How many events are in the array to wait on? HANDLE Event
; // Used to signal new clients assigned // to this thread HANDLE Thread
; // Handle to the curren thread HANDLE Handles
[ MAXIMUM_WAIT_OBJECTS
] ; // Array of socket's event handles CRITICAL_SECTION ThreadCritSec
; // Protect access to SOCKET_OBJ lists ThreadObj next
; // Next thread object in list} THREAD_OBJ
; CRITICAL_SECTION gThreadListCritSec
;ThreadObjHeader threadobjHeader
; void AssignIoToThread
( BUFFER_OBJ_EX
* buf
) ; SOCKET_OBJ
* GetSocketObj
( SOCKET s
, int af
) { SOCKET_OBJ
* sockobj
= NULL ; sockobj
= ( SOCKET_OBJ
* ) HeapAlloc
( GetProcessHeap
( ) , HEAP_ZERO_MEMORY
, sizeof ( SOCKET_OBJ
) ) ; if ( sockobj
= = NULL ) { fprintf ( stderr , "GetSocketObj: HeapAlloc failed: %d/n" , GetLastError
( ) ) ; ExitProcess
( - 1
) ; } sockobj
- > s
= s
; sockobj
- > af
= af
; InitializeCriticalSection
( & sockobj
- > SockCritSec
) ; return sockobj
;} void FreeSocketObj
( SOCKET_OBJ
* obj
){ BUFFER_OBJ
* ptr
= NULL , * tmp
= NULL ; if ( obj
- > OutstandingOps
! = 0
) { return ; } if ( obj
- > s
! = INVALID_SOCKET
) { closesocket
( obj
- > s
) ; obj
- > s
= INVALID_SOCKET
; } DeleteCriticalSection
( & obj
- > SockCritSec
) ; HeapFree
( GetProcessHeap
( ) , 0
, obj
) ;} BUFFER_OBJ_EX
* GetBufferObjEx
( SOCKET_OBJ
* sock
, int buflen
) { BUFFER_OBJ_EX
* newobj
= NULL ; newobj
= ( BUFFER_OBJ_EX
* ) HeapAlloc
( GetProcessHeap
( ) , HEAP_ZERO_MEMORY
, sizeof ( BUFFER_OBJ_EX
) ) ; if ( newobj
= = NULL ) { fprintf ( stderr , "GetBufferObj: HeapAlloc failed: %d/n" , GetLastError
( ) ) ; ExitProcess
( - 1
) ; } newobj
- > buf
= ( char * ) HeapAlloc
( GetProcessHeap
( ) , HEAP_ZERO_MEMORY
, sizeof ( BYTE
) * buflen
) ; if ( newobj
- > buf
= = NULL ) { fprintf ( stderr , "GetBufferObj: HeapAlloc failed: %d/n" , GetLastError
( ) ) ; ExitProcess
( - 1
) ; } newobj
- > buflen
= buflen
; newobj
- > addrlen
= sizeof ( newobj
- > addr
) ; newobj
- > Socket = sock
; newobj
- > ol
. hEvent
= WSACreateEvent
( ) ; if ( newobj
- > ol
. hEvent
= = NULL ) { fprintf ( stderr , "WSACreateEvent failed./n" ) ; ExitProcess
( - 1
) ; } return newobj
;} BUFFER_OBJ_EX
* FindBufferObjEx
( THREAD_OBJ
* thread
, WSAEVENT hEvent
) { BufferObj
* ptr
= NULL ; BUFFER_OBJ_EX
* bufobj
= NULL ; EnterCriticalSection
( & thread
- > ThreadCritSec
) ; ptr
= ( BufferObj
* ) GotoNextDoubleList
( & ( thread
- > BufferList
) , & ( thread
- > BufferList
. head
) ) ; while ( ptr
) { bufobj
= ( BUFFER_OBJ_EX
* ) container_of
( BUFFER_OBJ_EX
, bufDList
, ptr
) ; if ( bufobj
- > ol
. hEvent
= = hEvent
) break ; ptr
= ( BufferObj
* ) GotoNextDoubleList
( & ( thread
- > BufferList
) , ptr
) ; } LeaveCriticalSection
( & thread
- > ThreadCritSec
) ; return bufobj
;} void FreeBufferObjEx
( BUFFER_OBJ_EX
* obj
){ // Close the event WSACloseEvent
( obj
- > ol
. hEvent
) ; obj
- > ol
. hEvent
= NULL ; // Free the buffers HeapFree
( GetProcessHeap
( ) , 0
, obj
- > buf
) ; HeapFree
( GetProcessHeap
( ) , 0
, obj
) ;} int InsertBufferObjExToThread
( THREAD_OBJ
* thread
, BUFFER_OBJ_EX
* buf
) { int ret
; EnterCriticalSection
( & thread
- > ThreadCritSec
) ; if ( thread
- > EventCount
< MAXIMUM_WAIT_OBJECTS
- 1
) { EnqueueDoubleList
( & ( thread
- > BufferList
) , & ( buf
- > bufDList
) ) ; thread
- > Handles
[ thread
- > EventCount
+ + ] = buf
- > ol
. hEvent
; ret
= NO_ERROR
; } else { ret
= SOCKET_ERROR
; } LeaveCriticalSection
( & thread
- > ThreadCritSec
) ; return ret
;} void RemoveBufferFromThread
( SOCKET_OBJ
* sock
, BUFFER_OBJ_EX
* buf
){ EnterCriticalSection
( & buf
- > Thread
- > ThreadCritSec
) ; // Remove buffer from the list RemoveDoubleList
( & buf
- > Thread
- > BufferList
, & buf
- > bufDList
) ; // Decrement the event count for the thread buf
- > Thread
- > EventCount
- - ; // Set the thread's event WSASetEvent
( buf
- > Thread
- > Event
) ; LeaveCriticalSection
( & buf
- > Thread
- > ThreadCritSec
) ; } THREAD_OBJ
* GetThreadObj
( ) { THREAD_OBJ
* thread
= NULL ; thread
= ( THREAD_OBJ
* ) HeapAlloc
( GetProcessHeap
( ) , HEAP_ZERO_MEMORY
, sizeof ( THREAD_OBJ
) ) ; if ( thread
= = NULL ) { fprintf ( stderr , "GetThreadObj:HeapAlloc failed./n" ) ; ExitProcess
( - 1
) ; } thread
- > Event
= WSACreateEvent
( ) ; if ( thread
- > Event
= = NULL ) { fprintf ( stderr , "GetThreadObj: WSACreateEvent failed./n" ) ; ExitProcess
( - 1
) ; } thread
- > Handles
[ 0
] = thread
- > Event
; thread
- > EventCount
= 1
; InitializeDoubleHead
( & thread
- > BufferList
) ; InitializeCriticalSection
( & thread
- > ThreadCritSec
) ; return thread
;} void RenumberEvents
( THREAD_OBJ
* thread
) { EnterCriticalSection
( & thread
- > ThreadCritSec
) ; BUFFER_OBJ_EX
* obj
= NULL ; int i
= 0
; BufferObj
* sptr
= NULL ; sptr
= ( BufferObj
* ) GotoNextDoubleList
( & ( thread
- > BufferList
) , & ( thread
- > BufferList
. head
) ) ; thread
- > EventCount
= 1
; while ( sptr
) { obj
= ( BUFFER_OBJ_EX
* ) container_of
( BUFFER_OBJ_EX
, bufDList
, sptr
) ; thread
- > Handles
[ thread
- > EventCount
+ + ] = obj
- > ol
. hEvent
; sptr
= ( BufferObj
* ) GotoNextDoubleList
( & ( thread
- > BufferList
) , sptr
) ; } LeaveCriticalSection
( & thread
- > ThreadCritSec
) ;} int PostRecv
( BUFFER_OBJ_EX
* recvobj
) { WSABUF wbuf
; DWORD bytes
, flags
; int rc
= NO_ERROR
; EnterCriticalSection
( & recvobj
- > Socket - > SockCritSec
) ; recvobj
- > operation
= OP_READ
; wbuf
. buf
= recvobj
- > buf
; wbuf
. len
= recvobj
- > buflen
; flags
= 0
; if ( gProtocol
= = IPPROTO_TCP ) { rc
= WSARecv
( recvobj
- > Socket - > s
, & wbuf
, 1
, & bytes
, & flags
, & recvobj
- > ol
, NULL ) ; } else { ExitProcess
( - 1
) ; } if ( rc
= = SOCKET_ERROR
) { rc
= NO_ERROR
; if ( WSAGetLastError
( ) ! = WSA_IO_PENDING
) { fprintf ( stderr , "PostRecv: WSARecv* failed: %d/n" , WSAGetLastError
( ) ) ; rc
= SOCKET_ERROR
; } } // Increment outstanding overlapped operations InterlockedIncrement
( & recvobj
- > Socket - > OutstandingOps
) ; LeaveCriticalSection
( & recvobj
- > Socket - > SockCritSec
) ; return NO_ERROR
;} int PostSend
( BUFFER_OBJ_EX
* sendobj
) { WSABUF wbuf
; DWORD bytes
; int rc
; rc
= NO_ERROR
; sendobj
- > operation
= OP_WRITE
; wbuf
. buf
= sendobj
- > buf
; wbuf
. len
= sendobj
- > buflen
; EnterCriticalSection
( & sendobj
- > Socket - > SockCritSec
) ; if ( gProtocol
= = IPPROTO_TCP ) { rc
= WSASend
( sendobj
- > Socket - > s
, & wbuf
, 1
, & bytes
, 0
, & sendobj
- > ol
, NULL ) ; } else { ExitProcess
( - 1
) ; } if ( rc
= = SOCKET_ERROR
) { rc
= NO_ERROR
; if ( WSAGetLastError
( ) ! = WSA_IO_PENDING
) { fprintf ( stderr , "PostSend: WSASend* failed: %d/n" , WSAGetLastError
( ) ) ; rc
= SOCKET_ERROR
; } } // Increment the outstanding operation count InterlockedIncrement
( & sendobj
- > Socket - > OutstandingOps
) ; LeaveCriticalSection
( & sendobj
- > Socket - > SockCritSec
) ; return rc
;} int PostAccept
( BUFFER_OBJ_EX
* acceptobj
) { DWORD bytes
; int rc
= NO_ERROR
; acceptobj
- > operation
= OP_ACCEPT
; EnterCriticalSection
( & acceptobj
- > Socket - > SockCritSec
) ; acceptobj
- > sclient
= socket ( acceptobj
- > Socket - > af
, SOCK_STREAM , IPPROTO_TCP ) ; if ( acceptobj
- > sclient
= = INVALID_SOCKET
) { fprintf ( stderr , "PostAccept: create socket failed./n" ) ; return - 1
; } rc
= acceptobj
- > Socket - > lpfnAcceptEx
( acceptobj
- > Socket - > s
, acceptobj
- > sclient
, acceptobj
- > buf
, acceptobj
- > buflen
- ( ( sizeof ( SOCKADDR_STORAGE
) + 16
) * 2
) , sizeof ( SOCKADDR_STORAGE
) + 16
, sizeof ( SOCKADDR_STORAGE
) + 16
, & bytes
, & acceptobj
- > ol
) ; if ( rc
= = FALSE ) { if ( WSAGetLastError
( ) ! = WSA_IO_PENDING
) { fprintf ( stderr , "PostAccept: AcceptEx failed: %d/n" , WSAGetLastError
( ) ) ; ExitProcess
( - 1
) ; } } InterlockedIncrement
( & acceptobj
- > Socket - > OutstandingOps
) ; LeaveCriticalSection
( & acceptobj
- > Socket - > SockCritSec
) ; return rc
;} void HandleIo
( BUFFER_OBJ_EX
* buf
) { SOCKET_OBJ
* sock
= NULL , * clientobj
= NULL ; // New client object for accepted connections BUFFER_OBJ_EX
* recvobj
= NULL , // Used to post new receives on accepted connections * sendobj
= NULL ; // Used to post sends for data received DWORD bytes
, flags
; BOOL bFreeSocketObj
; int error , rc
; sock
= buf
- > Socket ; error = NO_ERROR
; bFreeSocketObj
= FALSE ; InterlockedDecrement
( & sock
- > OutstandingOps
) ; rc
= WSAGetOverlappedResult
( sock
- > s
, & buf
- > ol
, & bytes
, FALSE , & flags
) ; if ( rc
= = FALSE ) { fprintf ( stderr , "HandleIo: WSAGetOverlappedResult failed./n" ) ; ExitProcess
( - 1
) ; } if ( buf
- > operation
= = OP_ACCEPT
) { SOCKADDR_STORAGE
* LocalSockaddr
= NULL , * RemoteSockaddr
= NULL ; int LocalSockaddrLen
, RemoteSockaddrLen
; sock
- > lpfnGetAcceptExSockaddrs
( buf
- > buf
, buf
- > buflen
- ( ( sizeof ( SOCKADDR_STORAGE
) + 16
) * 2
) , sizeof ( SOCKADDR_STORAGE
) + 16
, sizeof ( SOCKADDR_STORAGE
) + 16
, ( SOCKADDR * * ) & LocalSockaddr
, & LocalSockaddrLen
, ( SOCKADDR * * ) & RemoteSockaddr
, & RemoteSockaddrLen
) ; clientobj
= GetSocketObj
( buf
- > sclient
, buf
- > Socket - > af
) ; sendobj
= GetBufferObjEx
( clientobj
, gBufferSize
) ; sendobj
- > buflen
= bytes
; memcpy ( sendobj
- > buf
, buf
- > buf
, bytes
) ; AssignIoToThread
( sendobj
) ; if ( PostSend
( sendobj
) ! = NO_ERROR
) { RemoveBufferFromThread
( clientobj
, sendobj
) ; FreeBufferObjEx
( sendobj
) ; closesocket
( clientobj
- > s
) ; clientobj
- > s
= INVALID_SOCKET
; FreeSocketObj
( clientobj
) ; } PostAccept
( buf
) ; } else if ( ( buf
- > operation
= = OP_READ
) & & ( error = = NO_ERROR
) ) { if ( ( bytes
> 0
) | | ( gProtocol
= = IPPROTO_UDP ) ) { // Create a buffer to send sendobj
= buf
; sendobj
- > buflen
= bytes
; // Initiate the send if ( PostSend
( sendobj
) ! = NO_ERROR
) { // In the event of an error, clean up the socket object RemoveBufferFromThread
( sock
, sendobj
) ; FreeBufferObjEx
( sendobj
) ; closesocket
( sock
- > s
) ; sock
- > s
= INVALID_SOCKET
; bFreeSocketObj
= TRUE ; } } else { // Graceful close sock
- > bClosing
= TRUE ; // Free the completed operation RemoveBufferFromThread
( sock
, buf
) ; FreeBufferObjEx
( buf
) ; // Check to see if there are more outstanding operations. If so, wait // for them to complete; otherwise, clean up the socket object. EnterCriticalSection
( & sock
- > SockCritSec
) ; if ( sock
- > OutstandingOps
= = 0
) { closesocket
( sock
- > s
) ; bFreeSocketObj
= TRUE ; } LeaveCriticalSection
( & sock
- > SockCritSec
) ; } } else if ( buf
- > operation
= = OP_WRITE
) { EnterCriticalSection
( & sock
- > SockCritSec
) ; if ( sock
- > bClosing
& & ( sock
- > OutstandingOps
= = 0
) ) { RemoveBufferFromThread
( sock
, buf
) ; closesocket
( sock
- > s
) ; FreeBufferObjEx
( buf
) ; bFreeSocketObj
= TRUE ; } else { buf
- > buflen
= gBufferSize
; // Free the send op that just completed if ( PostRecv
( buf
) ! = NO_ERROR
) { RemoveBufferFromThread
( sock
, buf
) ; FreeBufferObjEx
( buf
) ; } } LeaveCriticalSection
( & sock
- > SockCritSec
) ; }} DWORD WINAPI IoThread
( LPVOID lpParam
) { THREAD_OBJ
* thread
= NULL ; int index
, count , rc
, i
; thread
= ( THREAD_OBJ
* ) lpParam
; RenumberEvents
( thread
) ; while ( true ) { rc
= WaitForMultipleObjects
( thread
- > EventCount
, thread
- > Handles
, FALSE , INFINITE
) ; if ( rc
= = WAIT_FAILED
| | rc
= = WAIT_TIMEOUT
) { if ( GetLastError
( ) = = ERROR_INVALID_HANDLE
) { RenumberEvents
( thread
) ; continue ; } else { fprintf ( stderr , "IoThread: WaitForMultipleObjects failed: %d/n" , GetLastError
( ) ) ; break ; } } count = thread
- > EventCount
; for ( i
= 0
; i
< count ; + + i
) { rc
= WaitForSingleObject
( thread
- > Handles
[ i
] , 0
) ; if ( rc
= = WAIT_TIMEOUT
) continue ; index
= i
; WSAResetEvent
( thread
- > Handles
[ index
] ) ; if ( index
= = 0
) { RenumberEvents
( thread
) ; break ; } else { HandleIo
( FindBufferObjEx
( thread
, thread
- > Handles
[ index
] ) ) ; } } } ExitThread
( 0
) ; return 0
;} void AssignIoToThread
( BUFFER_OBJ_EX
* buf
) { ThreadObj
* threadObj
; THREAD_OBJ
* thread
; EnterCriticalSection
( & gThreadListCritSec
) ; threadObj
= ( ThreadObj
* ) GotoNextSingleList
( & threadobjHeader
, threadobjHeader
. head
) ; while ( threadObj
) { thread
= ( THREAD_OBJ
* ) container_of
( THREAD_OBJ
, next
, threadObj
) ; if ( InsertBufferObjExToThread
( thread
, buf
) = = NO_ERROR
) { break ; } threadObj
= ( ThreadObj
* ) GotoNextSingleList
( & threadobjHeader
, threadObj
) ; } if ( threadObj
= = NULL ) { thread
= GetThreadObj
( ) ; thread
- > Thread
= CreateThread
( NULL , 0
, IoThread
, ( LPVOID
) thread
, 0
, NULL ) ; if ( thread
- > Thread
= = NULL ) { fprintf ( stderr , "AssignIoToThread: CreateThread failed./n" ) ; ExitProcess
( - 1
) ; } InsertBufferObjExToThread
( thread
, buf
) ; EnqueueSingleListHead
( & threadobjHeader
, & ( thread
- > next
) ) ; } buf
- > Thread
= thread
; WSASetEvent
( thread
- > Event
) ; LeaveCriticalSection
( & gThreadListCritSec
) ;} int _tmain
( int argc
, _TCHAR
* argv
[ ] ){ WSADATA wsd
; THREAD_OBJ
* thread
= NULL ; SOCKET_OBJ
* sockobj
= NULL ; SocketObjHeader ListenSockets
; int endpointcount
= 0
, interval
= 0
, rc
, i
; struct addrinfo * res
= NULL , * ptr
= NULL ; if ( WSAStartup
( MAKEWORD
( 2
, 2
) , & wsd
) ! = 0
) { fprintf ( stderr , "unable to load Winsock!/n" ) ; return - 1
; } InitializeCriticalSection
( & gThreadListCritSec
) ; InitializeSingleHead
( & ListenSockets
) ; InitializeSingleHead
( & threadobjHeader
) ; res
= ResolveAddress
( gSrvAddr
, gPort
, gAddressFamily
, gSocketType
, gProtocol
) ; if ( res
= = NULL ) { fprintf ( stderr , "ResolveAddress failed to return any addresses!/n" ) ; return - 1
; } ptr
= res
; while ( ptr
) { sockobj
= GetSocketObj
( INVALID_SOCKET
, ptr
- > ai_family
) ; sockobj
- > s
= socket ( ptr
- > ai_family
, ptr
- > ai_socktype
, ptr
- > ai_protocol
) ; if ( sockobj
- > s
= = INVALID_SOCKET
) { fprintf ( stderr , "socket failed: %d/n" , WSAGetLastError
( ) ) ; return - 1
; } rc
= bind ( sockobj
- > s
, ptr
- > ai_addr
, ptr
- > ai_addrlen
) ; if ( rc
= = SOCKET_ERROR
) { fprintf ( stderr , "bind failed: %d/n" , WSAGetLastError
( ) ) ; return - 1
; } if ( gProtocol
= = IPPROTO_TCP ) { BUFFER_OBJ_EX
* acceptobj
= NULL ; GUID guidAcceptEx
= WSAID_ACCEPTEX
, guidGetAcceptExSockaddrs
= WSAID_GETACCEPTEXSOCKADDRS
; DWORD bytes
; rc
= WSAIoctl
( sockobj
- > s
, SIO_GET_EXTENSION_FUNCTION_POINTER
, & guidAcceptEx
, sizeof ( guidAcceptEx
) , & sockobj
- > lpfnAcceptEx
, sizeof ( sockobj
- > lpfnAcceptEx
) , & bytes
, NULL , NULL ) ; if ( rc
= = SOCKET_ERROR
) { fprintf ( stderr , "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d/n" , WSAGetLastError
( ) ) ; return - 1
; } rc
= WSAIoctl
( sockobj
- > s
, SIO_GET_EXTENSION_FUNCTION_POINTER
, & guidGetAcceptExSockaddrs
, sizeof ( guidGetAcceptExSockaddrs
) , & sockobj
- > lpfnGetAcceptExSockaddrs
, sizeof ( sockobj
- > lpfnGetAcceptExSockaddrs
) , & bytes
, NULL , NULL ) ; if ( rc
= = SOCKET_ERROR
) { fprintf ( stderr , "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d/n" , WSAGetLastError
( ) ) ; return - 1
; } rc
= listen ( sockobj
- > s
, 200
) ; if ( rc
= = SOCKET_ERROR
) { fprintf ( stderr , "listen failed: %d/n" , WSAGetLastError
( ) ) ; return - 1
; } sockobj
- > PendingAccepts
= ( BUFFER_OBJ_EX
* * ) HeapAlloc
( GetProcessHeap
( ) , HEAP_ZERO_MEMORY
, ( sizeof ( BUFFER_OBJ
* ) * gOverlappedCount
) ) ; if ( sockobj
- > PendingAccepts
= = NULL ) { fprintf ( stderr , "PendingAccepts HeapAlloc failed: %d/n" , GetLastError
( ) ) ; ExitProcess
( - 1
) ; } for ( i
= 0
; i
< gOverlappedCount
; + + i
) { sockobj
- > PendingAccepts
[ i
] = acceptobj
= GetBufferObjEx
( sockobj
, gBufferSize
) ; AssignIoToThread
( acceptobj
) ; if ( PostAccept
( acceptobj
) ! = NO_ERROR
) { ExitProcess
( - 1
) ; } } EnqueueSingleList
( & ListenSockets
, & ( sockobj
- > next
) ) ; } ptr
= ptr
- > ai_next
; } freeaddrinfo ( res
) ; while ( true ) { Sleep ( 5000
) ; interval
+ + ; if ( interval
= = 12
) { SocketObj
* listenptr
= NULL ; int optval
, optlen
; // Walk the list of outstanding accepts listenptr
= ( SocketObj
* ) GotoNextSingleList
( & ListenSockets
, ListenSockets
. head
) ; while ( listenptr
) { sockobj
= ( SOCKET_OBJ
* ) container_of
( SOCKET_OBJ
, next
, listenptr
) ; for ( i
= 0
; i
< gOverlappedCount
; i
+ + ) { optlen
= sizeof ( optval
) ; rc
= getsockopt ( sockobj
- > PendingAccepts
[ i
] - > sclient
, SOL_SOCKET
, SO_CONNECT_TIME
, ( char * ) & optval
, & optlen
) ; if ( rc
= = SOCKET_ERROR
) { fprintf ( stderr , "getsockopt: SO_CONNECT_TIME failed: %d/n" , WSAGetLastError
( ) ) ; return - 1
; } if ( ( optval
! = 0xFFFFFFFF
) & & ( optval
> 300
) ) { closesocket
( sockobj
- > PendingAccepts
[ i
] - > sclient
) ; } } listenptr
= ( SocketObj
* ) GotoNextSingleList
( & ListenSockets
, listenptr
) ; } interval
= 0
; } } WSACleanup
( ) ; return 0
;}
版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。