#include #include #include #include #define TAG printf( "# %s:%s(%d)\n", __FILE__, __FUNCTION__, __LINE__ ) #define DIEIF( a ) ( !( a ) || exceptionExit( __FILE__, __LINE__, #a, TRUE ) ) #define WARNIF( a ) ( !( a ) || exceptionExit( __FILE__, __LINE__, #a, FALSE ) ) #define HOST "127.0.0.1" #define PORT 12345 #define BUFSIZE 4096 SOCKET newListener( struct sockaddr_in *iFace ) { SOCKET lsn = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); DIEIF( iFace->sin_addr.s_addr == INADDR_NONE ); DIEIF( lsn == INVALID_SOCKET ); DIEIF( bind( lsn, (struct sockaddr*)iFace, sizeof(struct sockaddr_in ) ) == SOCKET_ERROR ); DIEIF( listen( lsn, SOMAXCONN ) == SOCKET_ERROR ); return lsn; } DWORD tServer( void *_client ) { SOCKET client = (SOCKET)_client; char buf[ 4096 ]; int read = 0, count = 0; printf( "Thread started for client %d\n", client ); while( read = recv( client, buf, 4096, 0 ) ) { int sent = 0; DIEIF( read == SOCKET_ERROR ); while( sent < read ) { sent = send( client, buf+sent, read-sent, 0 ); DIEIF( sent == SOCKET_ERROR ); if( !sent ) return 0; } ++count; } DIEIF( shutdown( client, 2 ) == SOCKET_ERROR ); printf( "Thread completed %d echos for client %d\n", count, client ); return 1; } DWORD tListener( void *arg ) { SOCKET lsn = (SOCKET)arg; SOCKET client; struct sockaddr_in addr; int size = sizeof( struct sockaddr_in ); while( DIEIF( ( client = accept( lsn, (struct sockaddr *)&addr, &size ) ) == INVALID_SOCKET ) ) { DWORD tid; printf( "Connect from: %d\n", client ); DIEIF( CreateThread( 0, 0, tServer, (void*)client, 0, &tid ) == NULL ); } return 1; } DWORD tClient ( void*_iFace ) { int i; char in[ BUFSIZE ], out[ BUFSIZE ]; SOCKET svr = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); struct sockaddr_in iFace; DIEIF( svr == INVALID_SOCKET ); iFace.sin_family = AF_INET; iFace.sin_addr.s_addr = inet_addr( HOST ); iFace.sin_port = htons( PORT ); while( connect( svr, (struct sockaddr *)&iFace, sizeof(struct sockaddr_in) ) == SOCKET_ERROR ) { if( WSAGetLastError() != WSAECONNREFUSED ) return 0; } srand( GetCurrentThreadId() ); for( i = 0; i < BUFSIZE; ++i ) out[ i ] = rand() & 0xff; i = 1+rand(); while( i-- ) { int read, written, toSend = 1+ ( rand() & 0xfff ); written = send( svr, out, toSend, 0 ); read = recv( svr, in, 4096, 0 ); } shutdown( svr, 2 ); return 1; } void h( const wchar_t * exp, const wchar_t * func, const wchar_t * file, unsigned int line, uintptr_t pReserved ) { // wprintf( L"Ex:%s func:%s; file:%s line:%d\n", exp, func, file, line ); return; } int main( int argc, char **argv ) { int t; SOCKET lsn; WSADATA wsa; DWORD tid; struct sockaddr_in iFace; _set_invalid_parameter_handler( h ); iFace.sin_family = AF_INET; iFace.sin_addr.s_addr = inet_addr( HOST ); iFace.sin_port = htons( PORT ); DIEIF( WSAStartup( MAKEWORD(1, 1), &wsa ) != 0 ); lsn = newListener( &iFace ); DIEIF( CreateThread( 0, 0, tListener, (void*)lsn, 0, &tid ) == NULL ); { struct _stat s; WARNIF( _fstat( lsn, &s ) == -1 ); WARNIF( _tell( lsn ) == -1 ); WARNIF( _dup( lsn ) == -1 ); } for( t = 0; t < 2; ++t ) { DIEIF( CreateThread( 0,0, tClient, (void*)&iFace, 0, &tid ) == NULL ); } while( Sleep( 10000 ),1 ); return WSACleanup(); } int exceptionExit( char *file, int line, char* msg, BOOL fatal ) { DWORD eNum = GetLastError(); TCHAR sysMsg[256]; TCHAR* p; if( eNum ) { FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), sysMsg, 256, NULL ); p = sysMsg; while( ( *p > 31 ) || ( *p == 9 ) ) ++p; do { *p-- = 0; } while( ( p >= sysMsg ) && ( ( *p == '.' ) || ( *p < 33 ) ) ); } else { eNum = errno; sprintf( sysMsg, "%s\0", strerror( errno ) ); } fprintf( stderr, "%s(%u):%s\n\tfailed with error %d (%s)\n", file, line, msg, eNum, sysMsg ); if( fatal ) exit( eNum ); return 0; // Keep the compiler happy } #### C:\test>828831.exe 828831.c(115):_fstat( lsn, &s ) == -1 failed with error 9 (Bad file descriptor) 828831.c(116):_tell( lsn ) failed with error 9 (Bad file descriptor) 828831.c(117):_dup( lsn ) == -1 failed with error 9 (Bad file descriptor) Connect from: 120 Thread started for client 120 Connect from: 128 Thread started for client 128 Thread completed 4895 echos for client 128 Thread completed 11575 echos for client 120