Windows Socket IO模型之 Select模式

    技术2024-08-13  59

    # 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;}

     

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

    最新回复(0)