1

Take the following:

struct Header{
    std::size_t body_size;
};
struct Body{
    std::string data;
};
struct Packet{
    Header header;
    Body body;


};

Suppose now, that I want to send a Packet object over a tcp socket.

To do this, I want to serialise the Header into a std::string, which contains information about how large the body is, and send that string over through the socket.

But this serialised header string itself has a variable size since the body_size is not fixed, so how would I know how many bytes to read (of the serialised header string)

So what kind of protocols are used in sending data like this?

snakelovah18119
  • 121
  • 1
  • 7
  • For simple data you can serialize to JSON, or use a binary format like CBOR, or if you're up for a challenge, define your own data format with Google Protocol Buffers – Brady Dean Jul 16 '21 at 14:23
  • Make your protocol in a way that every frame is of the form `[size data]`. First you read the size, and then you read the rest of the packet. This may not be the best way, but it is known to work in stream-oriented sockets. – ichramm Jul 16 '21 at 14:23
  • Is there a reason you want to send the header as a string? TCP is a byte stream so you could send the `size_t` directly. – Brady Dean Jul 16 '21 at 14:31

1 Answers1

0

The most commonly used protocol for sending data over a TCP socket like you propose is HTTP.
In HTTP, the body size is sent as a string in the relevant header [request, response or chunk] with special characters (\r\n for a request or response, ; for a chunk) to identify the end of the size string.
You'll need to decide on your own special character; NULL would be the easiest for null terminated strings.

One of the key issues of sending data as you propose, is that TCP can split the data up into a number of (what are commonly called) packets, so the receiver may not receive the whole of your Packet at once.
BTW Packet is a poor name in this context.

You don't need to know the size of your complete Packet before you send it. You can call boost:asio async_write with a collection of const_buffers to send both the Header and Body of your Packet.

On the receive side, I recommend using async_read_some with a string buffer large enough for your whole Packet including the Header string.
You should be able to read the Body size from the characters before the NULL and calculate your Packet size from the Body size plus the number of characters before the NULL + 1 (for the NULL). If this is less that the size reported by your ReadHandler then your Body has been split across multiple TCP packets, so you'll need to receive the other packets to reconstruct your Packet Body.

Or, you could save yourself the trouble and simply use a tried and tested HTTP library like via-httplib or boost::beast.

kenba
  • 4,303
  • 1
  • 23
  • 40