mercredi 28 février 2018

Sequential communication failed with boost::asio::streambuf in binary way?

Using boost::asio, I'm coding network stuff. I tried to build a simple send-and-receive-string protocol. The sender first send the string size to the receiver. Then the sender sends the actual string to the receiver.

In particular, I designed the following two protocols.

  • A sender holding a string sends it to a receiver. Upon receiving it, the receiver shows the string.

  • Execute above protocol sequentially (two times).

I built the above protocols as shown below: If I execute this protocol once, that works fine. However, if i execute this protocol more than once (e.g. two times), the string size that the receiver receives gets wrong.

First time : 1365 bytes.

Second time : 779073 bytes. (just read not 779073 but 7790)

I found that os << data_size is not done in a binary way. "779073" is just sent as 6 bytes string. But the receiver just reads 4bytes of it. How to send a binary data and to receive a binary data using boost::asio and boost::asio::streambuf?

Receiver

// socket is already defined
// ** first step: recv data size
boost::asio::streambuf buf;
boost::asio::read(
   socket,
   buf, 
   boost::asio::transfer_exactly(sizeof(uint32_t))
);
std::istream is(&buf);
uint32_t read_len;
iss >>  read_len;

// ** second step: recv payload based on the data size
boost::asio::streambuf buf2;
read_len = boost::asio::read(socket, buf2, 
boost::asio::transfer_exactly(read_len), error);
cout << "  read "<< read_len << " bytes payload" << endl; 
std::istream is_payload(&buf2);
std::string str;
is_payload >> str;
cout << str << endl; 

Sender

// socket is already defined
string str=...;   // some string to be sent
// ** first step: tell the string size to the reciever
uint32_t data_size = str.size();
boost::asio::streambuf send_buf;
std::ostream os(&send_buf);
os << data_size;
size_t sent_byte = boost::asio::write(socket, send_buf.data());
cout << sent_byte << endl; // debug purpose

// ** second step: send the actual string (payload)
sent_byte = boost::asio::write(socket, boost::asio::buffer(reinterpret_cast<const char*>(&str[0]), data_size));
cout << sent_byte << endl; // debug purpose

Aucun commentaire:

Enregistrer un commentaire