Windows Socket I/O模型之 Select模式
2011-02-02 14:08
295 查看
# 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; }
版权声明:
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
相关文章推荐
- Windows Socket I/O模型之 WSAEventSelect模式
- Windows Socket I/O模型之 WSAAsyncSelect模式
- WINDOWS SOCKET编程SELECT模型使用
- vc++ windows socket I/O模型 WSAeventSelect 模型例子
- winsocket异步模型--select模式介绍
- Windows Socket I/O模型之 重叠I/O事件通知模式
- Windows socket之WSAEventSelect模型
- Windows Socket五种I/O模型——select模型
- Windows socket I/O模型 之 select(2)
- 利用 select 模型,实现一个 I/O 复用模式的服务器
- windows Socket编程之EventSelect网络模型
- Windows Socket编程的select模型
- Windows Socket五种I/O模型(一)——选择模型(Select)
- Windows socket之WSAEventSelect模型
- Windows Socket五种I/O模型——select模型
- Windows Socket五种I/O模型——select模型
- Windows socket之Select模型开发
- [网络编程]_[Socket]_[Socket 阻塞模式(blocking)下的 I/O模型(model) 之 Select 模型(model)初探]
- windows socket编程select模型使用
- [网络编程]_[Socket]_[Socket 阻塞模式(blocking)下的 I/O模型(model) 之 Select 模型(model)初探]