# include < winsock2. h># include < ws2tcpip. h># include "resolve.h"# include "public.h"typedef SINGLE_LIST_HEADER BuffHeader;typedef SINGLE_LIST BuffObj;typedef DOUBLE_LIST_HEADER SockObjHeader;typedef DOUBLE_LIST SockObj;typedef struct _SOCKET_OBJ{ SOCKET s; // Socket handle int listening; // Socket is a listening socket (TCP) int closing; // Indicates whether the connection is closing SOCKADDR_STORAGE addr; // Used for client's remote address int addrlen; // Length of the address BuffHeader buff; DOUBLE_LIST entry;} SOCKET_OBJ; SockObjHeader sockobjhead; SOCKET_OBJ* GetSocketObj( SOCKET s, int listening) { SOCKET_OBJ * sockobj = NULL ; sockobj = ( SOCKET_OBJ* ) HeapAlloc( GetProcessHeap( ) , HEAP_ZERO_MEMORY, sizeof ( SOCKET_OBJ) ) ; if ( sockobj = = NULL ) { fprintf ( stderr , "HeapAlloc failed./n" ) ; ExitProcess( - 1) ; } sockobj- > s = s; sockobj- > listening = listening; sockobj- > addrlen = sizeof ( sockobj- > addr) ; InitializeCriticalSection( & sockobj- > buff. SendRecvQueueCritSec) ; return sockobj;}void FreeSocketObj( SOCKET_OBJ * obj) { BuffObj * ptr = NULL ; BUFFER_OBJ * blk = NULL ; while ( true ) { ptr = DequeueSingleList( & obj- > buff) ; if ( ptr = = NULL ) break ; blk = ( BUFFER_OBJ * ) container_of( BUFFER_OBJ, next, ptr) ; FreeBufferObj( blk) ; } HeapFree( GetProcessHeap( ) , 0, obj) ;}int ReceivePendingData( SOCKET_OBJ * obj) { BUFFER_OBJ * buffobj = NULL ; int rc, ret; buffobj = GetBufferObj( gBufferSize) ; ret = 0; if ( gProtocol = = IPPROTO_TCP ) { rc = recv ( obj- > s, buffobj- > buf, buffobj- > buflen, 0) ; } else { ExitProcess( - 1) ; } if ( rc = = SOCKET_ERROR) { ExitProcess( - 1) ; } else if ( rc = = 0) { FreeBufferObj( buffobj) ; obj- > closing = TRUE ; if ( obj- > buff. head = = NULL ) { closesocket( obj- > s) ; ret = - 1; } } else { buffobj- > buflen = rc; EnqueueSingleList( & obj- > buff, & buffobj- > next) ; } return ret;}int SendPendingData( SOCKET_OBJ * sock) { BUFFER_OBJ * bufobj = NULL ; BuffObj * entry = NULL ; int nleft = 0, idx = 0, ret = 0, rc = 0; while ( entry = DequeueSingleList( & sock- > buff) ) { bufobj = ( BUFFER_OBJ * ) container_of( BUFFER_OBJ, next, entry) ; if ( gProtocol = = IPPROTO_TCP ) { nleft = bufobj- > buflen; idx = 0; while ( nleft > 0) { rc = send ( sock- > s, & ( bufobj- > buf[ idx] ) , nleft, 0) ; if ( rc = = SOCKET_ERROR) { ExitProcess( - 1) ; } else { idx + = rc; nleft - = rc; } } FreeBufferObj( bufobj) ; } else { ExitProcess( - 1) ; } } if ( sock- > closing = = TRUE ) { closesocket( sock- > s) ; ret = - 1; printf ( "Closing Connection./n" ) ; } return ret;}int _tmain( int argc, _TCHAR* argv[ ] ){ WSADATA wsd; SOCKET s; struct addrinfo * res = NULL ; struct addrinfo * ptr = NULL ; SOCKET_OBJ * sockobj = NULL ; int rc; struct fd_set fdread, fdwrite, fdexcept; struct timeval timeout; if ( WSAStartup( MAKEWORD( 2, 2) , & wsd) ! = 0) { fprintf ( stderr , "load winsock2 failed./n" ) ; return 0; } res = ResolveAddress( gSrvAddr, gPort, gAddressFamily, gSocketType, gProtocol) ; if ( res = = NULL ) { fprintf ( stderr , "resolve addr failed./n" ) ; return - 1; } InitializeDoubleHead( & sockobjhead) ; ptr = res; while ( ptr) { s = socket ( ptr- > ai_family, ptr- > ai_socktype, ptr- > ai_protocol) ; if ( s = = INVALID_SOCKET) { fprintf ( stderr , "create socket failed./n" ) ; break ; } sockobj = GetSocketObj( s, ( gProtocol = = IPPROTO_TCP ) ? TRUE : FALSE ) ; EnqueueDoubleList( & sockobjhead, & sockobj- > entry) ; rc = bind ( sockobj- > s, ptr- > ai_addr, ptr- > ai_addrlen) ; if ( rc = = SOCKET_ERROR) { fprintf ( stderr , "bind failed./n" ) ; return 0; } if ( gProtocol = = IPPROTO_TCP ) { rc = listen ( sockobj- > s, 200) ; if ( rc = = SOCKET_ERROR) { fprintf ( stderr , "listen failed: %d/n" , WSAGetLastError( ) ) ; return - 1; } } ptr = ptr- > ai_next; } freeaddrinfo ( res) ; while ( true ) { FD_ZERO( & fdread) ; FD_ZERO( & fdwrite) ; FD_ZERO( & fdexcept) ; SockObj * sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, & ( sockobjhead. head) ) ; SOCKET_OBJ * obj = NULL ; while ( sptr) { obj = ( SOCKET_OBJ * ) container_of( SOCKET_OBJ, entry, sptr) ; FD_SET( obj- > s, & fdread) ; FD_SET( obj- > s, & fdwrite) ; FD_SET( obj- > s, & fdexcept) ; sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, sptr) ; } timeout. tv_sec = 5; timeout. tv_usec = 0; rc = select ( 0, & fdread, & fdwrite, & fdexcept, & timeout) ; if ( rc = = SOCKET_ERROR) { fprintf ( stderr , "select failed./n" ) ; return - 1; } else if ( rc = = 0) { printf ( "Wait Time out./n" ) ; continue ; } sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, & ( sockobjhead. head) ) ; SockObj * tmp = NULL ; obj = NULL ; while ( sptr) { obj = ( SOCKET_OBJ * ) container_of( SOCKET_OBJ, entry, sptr) ; if ( FD_ISSET( obj- > s, & fdread) ) { if ( obj- > listening) { sockobj = ( SOCKET_OBJ * ) GetSocketObj( INVALID_SOCKET, FALSE ) ; s = accept ( obj- > s, ( SOCKADDR * ) & sockobj- > addr, & sockobj- > addrlen) ; if ( s = = INVALID_SOCKET) { fprintf ( stderr , "accept failed./n" ) ; return - 1; } sockobj- > s = s; EnqueueDoubleListHead( & sockobjhead, & sockobj- > entry) ; } else { if ( ReceivePendingData( obj) ! = 0) { printf ( "ReceivePendingData./n" ) ; tmp = sptr; sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, sptr) ; RemoveDoubleList( & sockobjhead, tmp) ; FreeSocketObj( obj) ; continue ; } if ( SendPendingData( obj) ! = 0) { tmp = sptr; sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, sptr) ; RemoveDoubleList( & sockobjhead, tmp) ; FreeSocketObj( obj) ; continue ; } } } if ( FD_ISSET( obj- > s, & fdwrite) ) { if ( SendPendingData( obj) ! = 0) { tmp = sptr; sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, sptr) ; RemoveDoubleList( & sockobjhead, tmp) ; FreeSocketObj( obj) ; continue ; } } if ( FD_ISSET( obj- > s, & fdexcept) ) { tmp = sptr; sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, sptr) ; RemoveDoubleList( & sockobjhead, tmp) ; FreeSocketObj( obj) ; } sptr = ( SockObj * ) GotoNextDoubleList( & sockobjhead, sptr) ; } } WSACleanup( ) ; return 0;}
版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。