Thread: Socket class OOD

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    29

    Socket class OOD

    I've made a class for sockets and now i want to hear your opinions on the OOD of it

    Can i optimize performance without ruining the OOD of it?
    Should an help class contain so much error handling ( and if yes, then do you know any better way of doing it ? ) or should each class that uses Socket contain error handling?

    Do you know any english / swedish book on OOA & OOD & OOP for C++ ?

    Code:
    #if defined(_WIN32)
       #include <windows.h>
       #include <winsock.h>
     
       #define socket_recive(Socket,buffer,len, flags) recv(Socket, (char*)buffer, len , flags)
       #define socket_send(Socket,buffer,len, flags) send(Socket, (char*)buffer, len , flags)
       #define socket_close closesocket
    #else
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <netdb.h>
       #include <arpa/inet.h>
     
       #define socket_recive read
       #define socket_send write
       #define socket_close close
    #endif
     
    #include <deque>
     
    class Socket
    {
    private:
       SOCKET m_Socket;
       std::deque<int> errorVector;
       bool IsOpened;
     
    public:
       Socket()
       {
          this->setIsOpened(false);
       }
     
       virtual ~Socket()
       {
          this->Close();
          this->errorVector.clear();
       }
     
       int retrieveError(int num)
       {
          return this->errorVector.at(num);
       }
     
    private:
       bool testForError(int func)
       {
          if(func != 0)
             this->insertError(func);
     
          return func == 0 ? true : false ;
       }
     
       void insertError(int errorVal)
       {
          this->errorVector.push_front(errorVal);
       }
     
     
       void setIsOpened(bool bVal)
       {
          this->IsOpened = bVal;
       }
     
       bool getIsOpened()
       {
          return this->IsOpened;
       }
     
    public:
       bool Open(int af, int type, int protocol)
       {
          if(this->getIsOpened() == true)
             return true;
     
          SOCKET tempSock = socket(af, type, protocol);
     
          if(tempSock == INVALID_SOCKET)
          {
             this->insertError( (int)tempSock );
             return false;
          }
          else
          {
             this->setIsOpened(true);
             this->m_Socket = tempSock;
             return true;
          }
       }
     
       bool Open(SOCKET sock)
       {
          if(this->getIsOpened() == true)
             return true;
     
          if(sock == INVALID_SOCKET)
          {
             this->insertError( (int)sock );
             return false;
          }
          else
          {
             this->setIsOpened(true);
             this->m_Socket = sock;
             return true;
          }
       }
     
       bool Close()
       {
          bool didSucceed = this->testForError( socket_close(this->m_Socket) );
          if(didSucceed)
          {
             this->setIsOpened(false);
             return true;
          }
          else return false;
       }
     
       bool Bind(sockaddr* name, int namelen)
       {
          return this->testForError( bind(this->m_Socket, name, namelen) );
       }
     
       bool Connect(sockaddr* name, int namelen)
       {
          return this->testForError( connect(this->m_Socket, name, namelen) );
       }
     
       bool Connect(std::string host, int port, int af)
       {
          hostent* he;
          if( (he = gethostbyname( host.c_str() )) == 0 )
             return false;
     
          sockaddr_in clientService;
          clientService.sin_family = af;
          clientService.sin_addr.s_addr = inet_addr( inet_ntoa( (**(in_addr**)he->h_addr_list ) ) );
          clientService.sin_port = htons( port );
     
          return this->testForError( connect(this->m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) ) );
       }
     
       bool Listen(int backlog)
       {
          return this->testForError( listen(this->m_Socket, backlog) );
       }
     
       Socket* Accept(sockaddr* addr, int* addrlen)
       {
          Socket* tempSock = new Socket();
          tempSock->Open( accept(this->m_Socket, addr, addrlen) );
          return tempSock;
       }
     
       int Receive(char* &buf, int len, int flags)
       {
          return socket_recive(this->m_Socket, buf, len, flags);
       }
       int Send(char* &buf, int len, int flags)
       {
          return socket_send(this->m_Socket, buf, len, flags);
       }
    };

  2. #2
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Code:
     void setIsOpened(bool bVal)
       {
          this->IsOpened = bVal;
       }
     
       bool getIsOpened()
       {
          return this->IsOpened;
       }
    These two functions seem completely unnecessary to me. For one, it's probably faster to type IsOpened = false than to type setIsOpened(false), plus you add calling overhead. I suppose if you're planning to change those functions in the future, it might make sense, but I can't imagine what you would need to change.

    Also, is it really necessary to store all the errors? If something fails, the calling code will probably deal with it right away.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    29
    i want to keep the accessor methods cause encapsulation is pretty important for a good OOD.
    Can't you flag the compiler to copy the code in the method each time called instead of calling the method itself ?

    Mabye i should remove the error handling but first i want to know how much intelligence help classes should have.

  4. #4
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    That's not encapsulation. The two functions I mentioned were private functions. There's no reason to protect the class from itself.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    That's still encapsulation, and it's fine to leave it as functions. If you call that function a hundred times in your class, but want to change the implementation of it later, that's still 99 fewer places to potentially forget to change.

    Those methods are already inline, so if the compiler thinks it will be faster by inlining the code it will. Getting rid of those functions should not affect the speed of the program and it is good OOP to leave them.

    If you want to optimize the code, then use a profiler to determine what code takes the most time in time-intensive situations. Don't waste time trying to optimize code just by looking at it (except of course if you can see obviously slow algorithms).

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    29
    Eh, whats a profiler?

  7. #7
    Registered User
    Join Date
    Oct 2005
    Posts
    29
    I've optimized it a lot and i've added lots of methods

    heres the new class:
    Code:
    #if defined(_WIN32)
    	#include <windows.h>
    	#include <winsock.h>
    
    	#define socket_connect connect
    	#define socket_close closesocket
    	#define socket_ioctl ioctlsocket
    #else
    	#include <sys/socket.h>
    	#include <netinet/in.h>
    	#include <netdb.h>
    	#include <arpa/inet.h>
    	#include <sys/ioctl>
    
    	typedef SOCKET int
    	#define INVALID_SOCKET -1
    	#define socket_close close
    	#define socket_ioctl ioctl
    	#define socket_connect(SOCKET s, sockaddr_in* name, namelen) connect(s, (const sockaddr*) name, sizeof(sockaddr) )
    #endif
    
    class Socket
    {
    private:
    	SOCKET m_socket;
    	bool IsOpened;
    
    private:
    	void setIsOpened(bool bVal)
    	{
    		this->IsOpened = bVal;
    	}
    
    	bool getIsOpened(void)
    	{
    		return this->IsOpened;
    	}
    
    	void setSocket(SOCKET s)
    	{
    		this->m_socket = s;
    	}
    
    	SOCKET getSocket(void)
    	{
    		return this->m_socket;
    	}
    
    public:
    	Socket(void)
    	{
    		this->setIsOpened(false);
    	}
    
    	virtual ~Socket(void)
    	{
    		this->Close();
    	}
    
    	bool Open(int af, int type, int protocol)
    	{
    		if(this->getIsOpened())
    			return true;
    
    		SOCKET tempSock = socket(af, type, protocol);
    
    		if(tempSock == INVALID_SOCKET)
    			return false;
    		else
    		{
    			this->setIsOpened(true);
    			this->setSocket(tempSock);
    			return true;
    		}
    	}
    
    	bool Open(SOCKET tempSock)
    	{
    		if(this->getIsOpened())
    			return true;
    
    		if(tempSock == INVALID_SOCKET)
    			return false;
    		else
    		{
    			this->setIsOpened(true);
    			this->setSocket(tempSock);
    			return true;
    		}
    	}
    
    	bool Close(void)
    	{
    		this->Shutdown(0x02);
    
    		if( socket_close(this->getSocket()) == 0 ? true : false )
    		{
    			this->setIsOpened(false);
    			return true;
    		}
    		else return false;
    	}
    
    	bool Bind(const sockaddr* name, int namelen)
    	{
    		return bind(this->getSocket(), name, namelen) == 0 ? true : false;
    	}
    
    	bool Connect(const sockaddr* name, int namelen)
    	{
    		return socket_connect(this->getSocket(), name, namelen) == 0 ? true : false;
    	}
    
    	bool Connect(const char* host, int port, int af)
    	{
    		hostent* he;
    		if( (he = gethostbyname(host)) == 0 )
    			return false;
    
    		sockaddr_in clientService;
    		clientService.sin_family = af;
    		clientService.sin_addr.s_addr = inet_addr( inet_ntoa( (**(in_addr**)he->h_addr_list ) ) );
    		clientService.sin_port = htons(port);
    
    		return socket_connect(this->getSocket(), (SOCKADDR*) &clientService, sizeof(clientService) ) == 0 ? true : false;
    	}
    
    	bool Connect(std::string host, int port, int af)
    	{
    		return this->Connect(host.c_str(), port, af);
    	}
    
    	bool Shutdown(int how)
    	{
    		shutdown(this->getSocket(), how);
    	}
    
    	bool Receive(char* &buffer, int &receivedBytes, int flags)
    	{
    		receivedBytes = recv(this->getSocket(), buffer, (int)strlen(buffer), flags);
    		return receivedBytes > 0 ? true : false;
    	}
    
    	bool Receive(std::string &buffer, int &receivedBytes, int flags)
    	{
    		char* cBuffer;
    		receivedBytes = recv(this->getSocket(), cBuffer, (int)strlen(cBuffer), flags);
    
    		buffer += cBuffer;
    		buffer = buffer.substr(0,receivedBytes);
    
    		return receivedBytes > 0 ? true : false;
    	}
    
    	bool Send(char* &buffer, int &sentBytes, int flags)
    	{
    		sentBytes = send(this->getSocket(), buffer, (int)strlen(buffer), flags);
    		return sentBytes > 0 ? true : false;
    	}
    
    	bool Send(std::string &buffer, int &sentBytes, int flags)
    	{
    		char* cBuffer = (char*)buffer.c_str();
    		sentBytes = send(this->getSocket(), cBuffer, (int)strlen(cBuffer), flags);
    
    		return sentBytes > 0 ? true : false;
    	}
    
    	bool Listen(int backlog)
    	{
    		return listen(this->getSocket(), backlog) == 0 ? true : false;
    	}
    
    	Socket* Accept(sockaddr* addr, int* addrlen)
    	{
    		Socket* tempSock = new Socket();
    		tempSock->Open( accept(this->getSocket(), addr, addrlen) );
    		return tempSock;
    	}
    
    	bool getPeerName(sockaddr* name, int* namelen)
    	{
    		return getpeername(this->getSocket(), name, namelen) == 0 ? true : false;
    	}
    
    	bool getName(sockaddr* name, int* namelen)
    	{
    		return getsockname(this->getSocket(), name, namelen) == 0 ? true : false;
    	}
    
    	bool getOption(int level, int optionName, char* optionValue)
    	{
    		return getsockopt(this->getSocket(), level, optionName, optionValue, (int*)strlen(optionValue) ) == 0 ? true : false;
    	}
    
    	bool setOption(int level, int optionName, const char* optionValue)
    	{
    		return setsockopt(this->getSocket(), level, optionName, optionValue, (int)strlen(optionValue) ) == 0 ? true : false;
    	}
    
    	bool ioctl(long cmd, unsigned long* argp)
    	{
    		socket_ioctl(this->getSocket(), cmd, argp);
    	}
    };
    So , what do you think about it?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inherite nonvirtual class functionality
    By DrSnuggles in forum C++ Programming
    Replies: 2
    Last Post: 04-30-2009, 01:52 PM
  2. class composition constructor question...
    By andrea72 in forum C++ Programming
    Replies: 3
    Last Post: 04-03-2008, 05:11 PM
  3. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  4. c++ socket class
    By whitenoise in forum C++ Programming
    Replies: 1
    Last Post: 07-16-2002, 07:56 AM