# include < winsock2. h># include < ws2tcpip. h># include "resolve.h"# include "public.h"typedef SINGLE_LIST_HEADER BuffHeader;typedef struct _CONNECTION_OBJ{ SOCKET s; // Client socket HANDLE hRecvSema; // Semaphore incremented for each receive BuffHeader buff;} CONNECTION_OBJ;volatile LONG gConnectedClients = 0; CONNECTION_OBJ* GetConnectObj( SOCKET s) { CONNECTION_OBJ * newobj = NULL ; newobj = ( CONNECTION_OBJ * ) HeapAlloc( GetProcessHeap( ) , HEAP_ZERO_MEMORY, sizeof ( CONNECTION_OBJ) ) ; if ( newobj = = NULL ) { fprintf ( stderr , "heapalloc failed./n" ) ; ExitProcess( - 1) ; } newobj- > s = s; newobj- > hRecvSema = CreateSemaphore( NULL , 0, 0x0FFFFFFF, NULL ) ; if ( newobj- > hRecvSema = = NULL ) { fprintf ( stderr , "createsimaphore failed./n" ) ; ExitProcess( - 1) ; } newobj- > buff. head = newobj- > buff. tail = NULL ; InitializeCriticalSection( & newobj- > buff. SendRecvQueueCritSec) ; return newobj;}void FreeConnectionObj( CONNECTION_OBJ * obj) { DeleteCriticalSection( & obj- > buff. SendRecvQueueCritSec) ; HeapFree( GetProcessHeap( ) , 0, obj) ;} DWORD WINAPI ReceiveThread( LPVOID lpParam) { CONNECTION_OBJ * ConnObj= NULL ; BUFFER_OBJ * BuffObj= NULL ; int rc; ConnObj = ( CONNECTION_OBJ * ) lpParam; if ( gProtocol = = IPPROTO_TCP ) { while ( true ) { BuffObj = GetBufferObj( gBufferSize) ; rc = recv ( ConnObj- > s, BuffObj- > buf, BuffObj- > buflen, 0) ; BuffObj- > buflen = rc; EnqueueBufferObj( & ConnObj- > buff, & ( BuffObj- > next) ) ; ReleaseSemaphore( ConnObj- > hRecvSema, 1, NULL ) ; if ( rc = = 0 | | rc = = SOCKET_ERROR) { break ; } else if ( rc ! = SOCKET_ERROR) { printf ( "Read Bytes: %d/n" , rc) ; } } } ExitProcess( 0) ; return 0;} DWORD WINAPI SendThread( LPVOID lpParam) { CONNECTION_OBJ * ConnObj= NULL ; BUFFER_OBJ * BuffObj= NULL ; int rc, nleft, idx; SINGLE_LIST* block; ConnObj = ( CONNECTION_OBJ* ) lpParam; while ( true ) { rc = WaitForSingleObject( ConnObj- > hRecvSema, INFINITE) ; if ( ( rc = = WAIT_FAILED) | | ( rc = = WAIT_TIMEOUT) ) { fprintf ( stderr , "Send thread failed./n" ) ; ExitProcess( - 1) ; } block = DequeueBufferObj( & ConnObj- > buff) ; if ( block = = NULL ) ExitProcess( - 1) ; BuffObj = ( BUFFER_OBJ* ) container_of( BUFFER_OBJ, next, block) ; if ( ( ( gProtocol = = IPPROTO_TCP ) & & ( BuffObj- > buflen = = 0) ) | | ( BuffObj- > buflen = = SOCKET_ERROR) ) { FreeBufferObj( BuffObj) ; BuffObj = NULL ; break ; } if ( gProtocol = = IPPROTO_TCP ) { nleft = BuffObj- > buflen; idx = 0; while ( nleft > 0) { rc = send ( ConnObj- > s, BuffObj- > buf, BuffObj- > buflen, 0) ; if ( rc = = SOCKET_ERROR) { break ; } else { nleft - = rc; idx + = rc; } } } FreeBufferObj( BuffObj) ; BuffObj = NULL ; } closesocket( ConnObj- > s) ; FreeConnectionObj( ConnObj) ; ExitProcess( - 1) ; return 0;} DWORD WINAPI ServerListenThread( LPVOID param) { CONNECTION_OBJ * ConnObj= NULL ; HANDLE hThread = NULL ; SOCKET s; int rc; s = ( SOCKET ) param; if ( gProtocol = = IPPROTO_TCP ) { SOCKADDR_STORAGE saAccept; SOCKET ns; int acceptlen = sizeof ( SOCKADDR_STORAGE) ; rc = listen ( s, 200) ; if ( rc = = SOCKET_ERROR) { fprintf ( stderr , "listen failed" ) ; return - 1; } while ( true ) { ns = accept ( s, ( SOCKADDR * ) & saAccept, & acceptlen) ; if ( ns = = INVALID_SOCKET) { fprintf ( stderr , "accept failed./n" ) ; return - 1; } InterlockedIncrement( & gConnectedClients) ; ConnObj = GetConnectObj( ns) ; hThread = CreateThread( NULL , 0, SendThread, ( LPVOID) ConnObj, 0, NULL ) ; if ( hThread = = NULL ) { fprintf ( stderr , "Create thread 0./n" ) ; return - 1; } CloseHandle( hThread) ; hThread = CreateThread( NULL , 0, ReceiveThread, ( LPVOID) ConnObj, 0, NULL ) ; if ( hThread = = NULL ) { fprintf ( stderr , "Create thread 1./n" ) ; return - 1; } CloseHandle( hThread) ; } } closesocket( s) ; ExitThread( 0) ; return 0;}int _tmain( int argc, _TCHAR* argv[ ] ){ WSADATA wsd; SOCKET s[ MAX_LISTEN_SOCKETS] ; HANDLE threads[ MAX_LISTEN_SOCKETS] ; struct addrinfo * res = NULL ; struct addrinfo * ptr = NULL ; int listencount = 0; int rc = 0; int i; if ( WSAStartup( MAKEWORD( 2, 2) , & wsd) ! = 0) { fprintf ( stderr , "unable load to winsock!/n" ) ; return - 1; } res = ResolveAddress( gSrvAddr, gPort, gAddressFamily, gSocketType, gProtocol) ; if ( res = = NULL ) { fprintf ( stderr , "resolve addr failed./n" ) ; return - 1; } ptr = res; while ( ptr) { if ( listencount > MAX_LISTEN_SOCKETS) { fprintf ( stderr , "big than MAX_LISTEN_SOCKETS./n" ) ; return - 1; } s[ listencount] = socket ( ptr- > ai_family, ptr- > ai_socktype, ptr- > ai_protocol) ; if ( s[ listencount] = = INVALID_SOCKET) { fprintf ( stderr , "socket failed./n" ) ; return - 1; } rc = bind ( s[ listencount] , ptr- > ai_addr, ptr- > ai_addrlen) ; if ( rc = = SOCKET_ERROR) { fprintf ( stderr , "bind failed.%d/n" , WSAGetLastError( ) ) ; return - 1; } threads[ listencount] = CreateThread( NULL , 0, ServerListenThread, ( LPVOID) s[ listencount] , 0, NULL ) ; if ( threads[ listencount] = = NULL ) { fprintf ( stderr , "Create listen task faileds./n" ) ; return - 1; } + + listencount; ptr = ptr- > ai_next; } freeaddrinfo ( res) ; while ( true ) { rc = WaitForMultipleObjects( listencount, threads, TRUE , INFINITE) ; if ( rc = = WAIT_TIMEOUT) { fprintf ( stderr , "wait timeout./n" ) ; return - 1; } else if ( rc = = WAIT_FAILED) { fprintf ( stderr , "wait error./n" ) ; return - 1; } else break ; } for ( i= 0; i < listencount ; i+ + ) { CloseHandle( threads[ i] ) ; } WSACleanup( ) ; return 0;}
版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。