Reputation:
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
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