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