Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Read From Socket into std::string

I am writing a program in c++ that uses c sockets. I need a function to receive data that I would like to return a string. I know this will not work:

std::string Communication::recv(int bytes) {
    std::string output;
    if (read(this->sock, output, bytes)<0) {
        std::cerr << "Failed to read data from socket.\n";
    }
    return output;
}

Because the read()* function takes a char array pointer for an argument. What is the best way to return a string here? I know I could theoretically read the data into a char array then convert that to a string but that seems wasteful to me. Is there a better way?

*I don't actually mind using something other that read() if there is a more fitting alternative

Here is all of the code on pastebin which should expire in a week. If I don't have an answer by then I will re-post it: http://pastebin.com/HkTDzmSt

[UPDATE]

I also tried using &output[0] but got the output contained the following:

jello!
[insert a billion bell characters here]

"jello!" was the data sent back to the socket.

like image 462
735Tesla Avatar asked Jan 22 '14 02:01

735Tesla


Video Answer


1 Answers

Here are some functions that should help you accomplish what you want. It assumes you'll only receive ascii character from the other end of the socket.

std::string Communication::recv(int bytes) {
    std::string output(bytes, 0);
    if (read(this->sock, &output[0], bytes-1)<0) {
        std::cerr << "Failed to read data from socket.\n";
    }
    return output;
}

or

std::string Communication::recv(int bytes) {
    std::string output;
    output.resize(bytes);

    int bytes_received = read(this->sock, &output[0], bytes-1);
    if (bytes_received<0) {
        std::cerr << "Failed to read data from socket.\n";
        return "";
    }

    output[bytes_received] = 0;
    return output;
}

When printing the string, be sure to use cout << output.c_str() since string overwrite operator<< and skip unprintable character until it reaches size. Ultimately, you could also resize at the end of the function to the size received and be able to use normal cout.

As pointed out in comments, sending the size first would also be a great idea to avoid possible unnecessary memory allocation by the string class.

like image 174
Eric Fortin Avatar answered Oct 21 '22 15:10

Eric Fortin