user6275678
user6275678

Reputation:

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!

Upvotes: 0

Views: 2328

Answers (1)

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140168

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

Upvotes: 4

Related Questions