Thread: Dynamic Arrays and recv()

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230

    Dynamic Arrays and recv()

    Hello everyone. I'm trying to write a socket class for fun and I'm just wondering what the best solution to my problem would be...

    Basically I'm trying to write the socket classes Read() function, but i want the user to be able to specify how many bytes to read (which will be parsed the recv()'s len parameter). So, to make it efficient, I want to dynamically allocate memory for an array the same size as the user specifies to read.

    The problem is (I'm assuming) since its dynamically allocated (therefore the memory is allocated at run-time) I cannot compile it because the compiler says "Undeclared Identifier", etc.

    Here's my code snippet:

    Code:
    char * Socket::Read(int sockfd, int len)
    {
    	// Default read and buffer length/size if
    	// user does not specify read amount.
    	int bufSize = 2048;
    
    	if (len)
    		char * buf = new char[len+1];
    	else
    		char * buf = new char[bufSize];
    
    	if (!sockfd)
    	{
    		if (!len)
    			recv(this->sockfd, buf, bufSize, 0);
    		else
    			recv(this->sockfd, buf, len, 0);
    	}
    
    	else
    	{
    		if (!len)
    			recv(sockfd, buf, bufSize, 0);
    		else
    			recv(sockfd, buf, len, 0);
    	}
    
    	return buf;
    }
    Thank you for any help you can provide
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

  2. #2
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Code:
    	if (len)
    		char * buf = new char[len+1];
    	else
    		char * buf = new char[bufSize];
    You're declaring it only for the if or for the else. Afterwards, the buf variable is no longer available, as it's outside of its scope. Try declaring buf before the if and assigning it in the if only.

  3. #3
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    Quote Originally Posted by EVOEx View Post
    Code:
    	if (len)
    		char * buf = new char[len+1];
    	else
    		char * buf = new char[bufSize];
    You're declaring it only for the if or for the else. Afterwards, the buf variable is no longer available, as it's outside of its scope. Try declaring buf before the if and assigning it in the if only.
    Wow... I can't believe I didn't see that... I feel like an idiot. Thanks for your help.
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

  4. #4
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    Hmm I have another question whilst I'm here. Since I'm returning buf for a different function to process the array, what should I do about deleting the memory? Because I need to use that array, and deleting it in the function that processes it is a really ugly way of doing it. I want things to be organized within the class.

    Edit: Never mind I took a different approach.

    Code:
    // Reads len amount of data from the socket and stores the data in a parsed buffer
    // Returns 0 on failure or number of bytes read on success
    int Socket::Read(int sockfd, char * recv_buf, int len, int flags)
    {
    	if (!len)
    		return 0;
    
    	int recv_len = recv(sockfd, recv_buf, len, flags);
    
    	if (recv_len == SOCKET_ERROR)
    		return 0;
    
    	return recv_len;
    }
    Last edited by pobri19; 07-02-2009 at 08:46 AM.
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Why are you passing the sockfd to the method? That sort of defeats the purpose of having a Socket class in the first place doesn't it?

    IMHO, a socket class looks like this:

    Code:
    class SocketBase
    {
    public:
        SocketBase( int sockfd )
            : mFd( sockfd )
        {
        }
    
        virtual ~SocketBase()
        {
            close( mFd );
        }
    };
    
    class Socket : public SocketBase
    {
    public:
        Socket( int sockfd )
            : SocketBase( sockfd )
        {
        }
    
        int Send( const char *data, int len )
        {
            return send( mFd, data, len, 0 );
        }
    
        int Receive( char *data, int len )
        {
            return recv( mFd, data, len, 0 );
        }
    };
    Of course you'd probably have a convenience constructor for Socket which creates the socket itself and connects to a port. At any rate the point is for the socket to own the fd so that it can close it when it gets destroyed. It's pointless to just wrap the socket API without also encapsulating the resource
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    Quote Originally Posted by brewbuck View Post
    Why are you passing the sockfd to the method? That sort of defeats the purpose of having a Socket class in the first place doesn't it?

    IMHO, a socket class looks like this:

    Code:
    class SocketBase
    {
    public:
        SocketBase( int sockfd )
            : mFd( sockfd )
        {
        }
    
        virtual ~SocketBase()
        {
            close( mFd );
        }
    };
    
    class Socket : public SocketBase
    {
    public:
        Socket( int sockfd )
            : SocketBase( sockfd )
        {
        }
    
        int Send( const char *data, int len )
        {
            return send( mFd, data, len, 0 );
        }
    
        int Receive( char *data, int len )
        {
            return recv( mFd, data, len, 0 );
        }
    };
    Of course you'd probably have a convenience constructor for Socket which creates the socket itself and connects to a port. At any rate the point is for the socket to own the fd so that it can close it when it gets destroyed. It's pointless to just wrap the socket API without also encapsulating the resource
    That's how I'm currently doing it, I just didn't want to force any restrictions so I'm giving the option of either using the classes socket or a user defined socket.
    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

Popular pages Recent additions subscribe to a feed