I've isolated the problem and present it for dissection. I can't find any
reason why it is blocking. I've even written a stand alone program which
does not block, so I don't think I'm making the mistake...
I'm using the latest version of MyServer from the svn repository.
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include "../include/base/socket/socket.h"
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
class TestSocket : public CppUnit::TestFixture
{
Socket *obj;
Socket *obj2; // use as client socket when needed
CPPUNIT_TEST_SUITE( TestSocket );
CPPUNIT_TEST( teststartupSocketLib );
CPPUNIT_TEST( testGetHandle );
CPPUNIT_TEST( testGethostbyaddr );
CPPUNIT_TEST( testGethostbyname );
CPPUNIT_TEST( testGethostname );
CPPUNIT_TEST( testSocket );
CPPUNIT_TEST( testBind );
CPPUNIT_TEST( testListen );
CPPUNIT_TEST( testAccept ); // blocks! it shouldn't, thought...
CPPUNIT_TEST( testSetsockopt );
CPPUNIT_TEST( testConnect );
CPPUNIT_TEST( testClose );
// CPPUNIT_TEST( testShutdown );
/* CPPUNIT_TEST( testRecv );
CPPUNIT_TEST( testBytesToRead );
CPPUNIT_TEST( testIoctlsocket );
CPPUNIT_TEST( testSocketSend );
CPPUNIT_TEST( testSocketConnect );
CPPUNIT_TEST( testGetsockname );
CPPUNIT_TEST( testSetNonBlocking );
CPPUNIT_TEST( testDataOnRead ); */
CPPUNIT_TEST( testGetLocalIPsList );
CPPUNIT_TEST_SUITE_END( );
public:
void setUp ( )
{
obj = new Socket;
obj2 = new Socket;
}
void tearDown ( )
{
delete obj;
delete obj2;
}
// do different Socket object creation
void teststartupSocketLib ( )
{
CPPUNIT_ASSERT_EQUAL( obj->startupSocketLib ( ), 0 );
}
// void setServerSocket ( Socket* );
// Socket* getServerSocket ( );
void testGetHandle ( )
{
CPPUNIT_ASSERT( obj->socket ( AF_INET, SOCK_STREAM, 0 ) != -1 );
CPPUNIT_ASSERT( int( obj->getHandle ( ) ) != -1 );
CPPUNIT_ASSERT( obj->close ( ) != -1 );
#if HAVE_IPV6
CPPUNIT_ASSERT( obj->socket ( AF_INET6, SOCK_STREAM, 0 ) != -1 );
CPPUNIT_ASSERT( int( obj->getHandle ( ) ) != -1 );
CPPUNIT_ASSERT( obj->close ( ) != -1 );
#endif
}
void testGethostbyaddr ( )
{
char host[] = "355.355.355.355";
int len = sizeof ( host ) / sizeof ( char );
// fail!
CPPUNIT_ASSERT( obj->gethostbyaddr ( host, len, AF_INET ) == NULL );
// const char host2[] = "MAKE THIS AN IPv6 address : )";
// int len2 = sizeof host / sizeof char;
// CPPUNIT_ASSERT( obj->gethostbyaddr ( host2, len2, AF_INET6 ) == NULL );
#if HAVE_IPV6
#endif
}
void testGethostbyname ( )
{
const char host[] = "localhost";
int len = sizeof ( host ) / sizeof ( char );
CPPUNIT_ASSERT( obj->gethostbyname ( host ) != NULL );
}
void testGethostname ( )
{
char host[] = "localhost";
int len = sizeof ( host ) / sizeof ( char );
int status = obj->gethostname ( host, len );
#if DEBUG
if ( status == -1 )
cout << "obj->gethostname ( host, len ): " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT_EQUAL( status, 0 );
}
// OK TILL HERE ?
// test the socket() method, not the constructor ; )
void testSocket ( )
{
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto ); // WARNING! Only tcp ?
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#if HAVE_IPV6
status = obj->socket ( AF_INET6, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#endif // HAVE_IPV6
}
void testBind ( )
{
int optvalReuseAddr = 1;
char host[] = "localhost";
MYSERVER_SOCKADDRIN sockIn = { 0 };
((sockaddr_in*) (&sockIn))->sin_family = AF_INET;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( 0 );
int sockInLen = sizeof ( sockaddr_in );
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
status = obj->bind ( &sockIn, sockInLen );
#if DEBUG
if ( status == -1 )
cout << "For obj->bind()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#if HAVE_IPV6
((sockaddr_in*) (&sockIn))->sin_family = AF_INET6;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( 0 );
int sockInLen6 = sizeof ( sockaddr_in6 );
int status = obj->socket ( AF_INET6, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) < 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->bind ( &sockIn, sockInLen6 );
#if DEBUG
if ( status == -1 )
cout << "For obj->bind()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#endif // HAVE_IPV6
}
void testListen ( )
{
int optvalReuseAddr = 1;
char host[] = "localhost";
MYSERVER_SOCKADDRIN sockIn = { 0 };
((sockaddr_in*) (&sockIn))->sin_family = AF_INET;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( 0 );
int sockInLen = sizeof ( sockaddr_in );
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
status = obj->bind ( &sockIn, sockInLen );
#if DEBUG
if ( status == -1 )
cout << "For obj->bind()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->listen ( 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->listen()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#if HAVE_IPV6
((sockaddr_in*) (&sockIn))->sin_family = AF_INET6;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( 0 );
int sockInLen6 = sizeof ( sockaddr_in6 );
int status = obj->socket ( AF_INET6, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) < 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->bind ( &sockIn, sockInLen6 );
#if DEBUG
if ( status == -1 )
cout << "For obj->bind()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->listen ( 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->listen()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#endif // HAVE_IPV6
}
void testAccept ( )
{
cout << "\nIn TestSocket::testAccept()\n";
int optvalReuseAddr = 1;
char host[] = "localhost";
int port = 6543;
MYSERVER_SOCKADDRIN sockA;
int sockALen = sizeof ( sockaddr_in );
MYSERVER_SOCKADDRIN sockIn = { 0 };
((sockaddr_in*) (&sockIn))->sin_family = AF_INET;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( port );
int sockInLen = sizeof ( sockaddr_in );
CPPUNIT_ASSERT( obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto ) != -1 );
CPPUNIT_ASSERT( obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) ) != -1 );
CPPUNIT_ASSERT( obj->bind ( &sockIn, sockInLen ) != -1 );
CPPUNIT_ASSERT( obj->listen ( 2 ) != -1 );
CPPUNIT_ASSERT( obj->setNonBlocking ( 1 ) == 0 );
CPPUNIT_ASSERT( int(obj->accept ( &sockA, &sockALen ).getHandle()) != -1 );
CPPUNIT_ASSERT( obj->close ( ) != -1 );
cout << "\nIn TestSocket::testAccept() 6\n";
#if HAVE_IPV6
((sockaddr_in*) (&sockIn))->sin_family = AF_INET6;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( port );
int sockInLen6 = sizeof ( sockaddr_in6 );
int sockALen6 = sizeof ( sockaddr_in6 );
int status = obj->socket ( AF_INET6, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) < 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->bind ( &sockIn, sockInLen6 );
#if DEBUG
if ( status == -1 )
cout << "For obj->bind()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->listen ( 2 );
#if DEBUG
if ( status == -1 )
cout << "For obj->listen()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setNonBlocking ( 1 );
#if DEBUG
if ( status == -1 )
cout << "For obj->setNonBlocking()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
Socket t6 = obj->accept ( &sockA, &sockALen6 );
#if DEBUG
if ( int(t6.getHandle) != -1 )
cout << "For obj->accept()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( int(t6.getHandle ( ) ) != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#endif // HAVE_IPV6
}
void testSetsockopt ( )
{
int optvalReuseAddr = 1;
char host[] = "localhost";
int status = obj->socket ( AF_INET, SOCK_STREAM, 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
#if HAVE_IPV6
status = obj->socket ( AF_INET, SOCK_STREAM, 0 );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->setsockopt ( SOL_SOCKET, SO_REUSEADDR, (const char*) &optvalReuseAddr, sizeof(optvalReuseAddr) );
#if DEBUG
if ( status == -1 )
cout << "For obj->setsockopt()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
#endif // HAVE_IPV6
cout << "\nOut of TestSocket::testAccept()\n";
}
void testConnect ( )
{
// init, bind, listen server; init client; fork; connect client; accept for client; close for both; exit child
char host[] = "localhost";
MYSERVER_SOCKADDRIN sockIn = { 0 };
((sockaddr_in*) (&sockIn))->sin_family = AF_INET;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( 0 );
int sockInLen = sizeof ( sockaddr_in );
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto ); // WARNING! Only tcp ?
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->bind ( &sockIn, sockInLen );
#if DEBUG
if ( status == -1 )
cout << "For obj->bind()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
//
// close both
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#if HAVE_IPV6
((sockaddr_in*) (&sockIn))->sin_family = AF_INET6;
((sockaddr_in*) (&sockIn))->sin_addr.s_addr = inet_addr ( "127.0.0.1" );
((sockaddr_in*) (&sockIn))->sin_port = htons ( 0 );
sockInLen6 = sizeof ( sockaddr_in6 );
#endif // HAVE_IPV6
}
void testClose ( )
{
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto ); // WARNING! Only tcp ?
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
#if HAVE_IPV6
#endif // HAVE_IPV6
}
void testShutdown ( )
{
/*
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto ); // WARNING! Only tcp ?
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->shutdown ( SHUT_RDWR );
#if DEBUG
if ( status == -1 )
cout << "For obj->shutdown()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
*/
}
void testRecv ( ) { }
void testBytesToRead ( ) { }
void testIoctlsocket ( ) { }
void testSocketSend ( ) { }
void testSocketConnect ( ) { }
// int operator==(Socket);
// int operator=(Socket);
void testGetsockname ( ) { }
void testSetNonBlocking ( ) { }
void testDataOnRead ( ) { }
// void testGetThrottling ( ) { }
// void testSetThrottling ( ) { }
void testGetLocalIPsList ( )
{
int status = obj->socket ( AF_INET, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
string out;
status = obj->getLocalIPsList ( out );
#if DEBUG
if ( status == -1 )
cout << "For obj->getLocalIPsList()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#if HAVE_IPV6
status = obj->socket ( AF_INET6, SOCK_STREAM, ( getprotobyname ( "tcp" ) )->p_proto );
#if DEBUG
if ( status == -1 )
cout << "For obj->socket()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
string out;
status = obj->getLocalIPsList ( out );
#if DEBUG
if ( status == -1 )
cout << "For obj->getLocalIPsList()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
status = obj->close ( );
#if DEBUG
if ( status == -1 )
cout << "For obj->close()\terrno: " << errno << "\t" << "strerror: " << strerror ( errno ) << endl;
#endif
CPPUNIT_ASSERT( status != -1 );
#endif // HAVE_IPV6
}
/*! Inherithed from Stream. */
/* virtual int read(char* buffer, u_long len, u_long *nbr);
virtual int write(const char* buffer, u_long len, u_long *nbw); */
};
CPPUNIT_TEST_SUITE_REGISTRATION( TestSocket );