Chuck Chuck - 5 days ago 5
C++ Question

C++ socket only sends first 4 bytes of data

I am currently writing a socket wrapper in C++ for Linux. It is basically a collection of classes that handle the creation, connection, sending, reading, and closing of a TCP socket.

In my socket class, all functions work well except for the send and receive function. They do not return an error; instead, it only sends the first four bytes of data.

My send function:

int Socket::sends(char* buffer){

int bytes; // for number of bytes sent

/* First, send the size of buffer */
int datalen = strlen(buffer); // get sizeof buffer
int len = htonl(datalen); // reformat

// send the size of the buffer
bytes = send(socketfd, (char*)&len, sizeof(len), 0); // send the size
if (bytes < 0){
cerr << "Error sending size of buffer to socket" << endl;
return 1;
}

/* Now acutally send the data */

bytes = send(socketfd, buffer, datalen, 0);
if (bytes < 0){
cerr << "Error writing buffer to socket" << endl;
return 1;
}

cout << bytes << " written" << endl;

return 0;

}


The ideas behind it is that It sends the buffer (
char* buffer
) by first sending the size of the buffer, and then sending the actual buffer. If an error is encountered (returning -1) the function terminates by returning 1.

Now, here is the read method:

int Socket::reads(char* buffer){

int bytes, buflen; // for bytes written and size of buffer

/* Read the incoming size */
bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0);
if (bytes < 0){
cerr << "Error reading size of data" << endl;
return 1;
}
buflen = ntohl(buflen);

/* Read the data */

bytes = recv(socketfd, buffer, buflen, 0);
if (bytes < 0){
cerr << "Error reading data" << endl;
return 1;
}

return 0;
}


Here, the idea is to read the size of the data first, and then set the buffer to that size and read into it. The function returns 1 on error (recv returns -1).

Using the methods would look something like this:

socket.sends("Hello World"); // socket object sends the message

char* buffer;
socket.reads(buffer); // reads into the buffer


However, when ever I use these functions, I only receive the first 4 bytes of data, followed by strange, non-ASCII characters. I have no idea why this happens. No error is not encountered in the
send
and
recv
functions, and the functions say that only 4 bytes were written. Is there a better way that I should send or receive data? I am overlooking a very simple error?

Thanks for your help!

Answer

you're passing an uninitialized pointer (buffer) to your reads method, which probably explains that it works partially (undefined behaviour).

And you shouldn't pass buffer as a parameter since it won't be modified (and you don't know the size yet anyway)

Plus, you have to null-terminate your message when you recieve it.

I would do like this:

 char *Socket::reads(){
    char* buffer;
    int bytes, buflen; // for bytes written and size of buffer

    /* Read the incoming size */
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0);
    if (bytes < 0){
        cerr << "Error reading size of data" << endl;
        return 1;
    }
    buflen = ntohl(buflen);
    buffer = new char[buflen+1]; // +1 for the NUL-terminator
    /* Read the data */

    bytes = recv(socketfd, buffer, buflen, 0);
    if (bytes < 0){
        cerr << "Error reading data" << endl;
        return 1;
    }
    buffer[buflen] = '\0'; // NUL-terminate the string

    return buffer;
}

the main:

socket.sends("Hello World"); // socket object sends the message

char* buffer = socket.reads(); // reads into the buffer

don't forget to delete [] the buffer in the end.

Could also be done with std::string or std::vector<char> to avoid new and delete

Comments