lundi 26 février 2018

How can we sequentially receive multiple data from boost::asio::tcp::ip::read_some calls?

Let us suppose that a client holds two different big objects (in terms of byte size) and serializes those followed by sending the serialized objects to a server over TCP/IP network connection using boost::asio.

  • For client side implementation, I'm using boost::asio::write to send binary data (const char*) to the server.

  • For server side implementation, I'm using read_some rather than boost::asio::ip::tcp::iostream for future improvement for efficiency. I built the following recv function at the server side. The second parameter std::stringstream &is holds a big received data (>65536 bytes) in the end of the function.

When the client side calls two sequential boost::asio::write in order to send two different binary objects separately, the server side sequentially calls two corresponding recv as well. However, the first recv function absorbs all of two incoming big data while the second call receives nothing ;-(. I am not sure why this happens and how to solve it.

Since each of two different objects has its own (De)Serialization function, I'd like to send each data separately. In fact, since there are more than 20 objects (not just 2) that have to be sent over the network.

void recv (
    boost::asio::ip::tcp::socket &socket,
    std::stringstream &is) {

    boost::array<char, 65536> buf;

    for (;;) {
        boost::system::error_code error;
        size_t len = socket.read_some(boost::asio::buffer(buf), error);
        std::cout << " read "<< len << " bytes" << std::endl;  // called multiple times for debugging!

        if (error == boost::asio::error::eof)
          break;
        else if (error)
          throw boost::system::system_error(error); // Some other error.

        std::stringstream buf_ss;
        buf_ss.write(buf.data(), len);
        is << buf_ss.str();
    }
}

Client main file:

int main () {
    ... // some 2 different big objects are constructed.
    std::stringstream ss1, ss2;
    ... // serializing bigObj1 -> ss1 and bigObj2-> ss2, where each object is serialized into a string. This is due to the dependency of our using some external library
    const char * big_obj_bin1 = reinterpret_cast<const char*>(ss1.str().c_str());
    const char * big_obj_bin2 = reinterpret_cast<const char*>(ss2.str().c_str());

    boost::system::error_code ignored_error;
    boost::asio::write(socket, boost::asio::buffer(big_obj_bin1, ss1.str().size()), ignored_error);
    boost::asio::write(socket, boost::asio::buffer(big_obj_bin2, ss2.str().size()), ignored_error);

    ... // do something
    return 0;
}

Server main file:

int main () {
    ... // socket is generated. (communication established)
    std::stringstream ss1, ss2;
    recv(socket,ss1); // this guy absorbs all of incoming data
    recv(socket,ss2); // this guy receives 0 bytes ;-(
    ... // deserialization to two bib objects
    return 0;
}

Aucun commentaire:

Enregistrer un commentaire