title: Sending a flexible Amount of Data over Network by using Asio (Boost)
body: <p>I got a client and a server application which will send each other data by using the Asio (Standalone) library. Both applications consists of two (logical) parts:</p>
  
  <ol>
  <li>A high level part: dealing with complex objects e.g. users, permissions,...</li>
  <li>A low level part: sending data over network between client and server</li>
  </ol>
  
  <p>Let's assume the complex objects are already serialized by using <a href="https://developers.google.com/protocol-buffers/" rel="nofollow">Protocoll Buffers</a> and the low level part of the application receives the data as std::string from the high level part. I would like to use this function from <a href="https://developers.google.com/protocol-buffers/docs/cpptutorial" rel="nofollow">Protocoll Buffers</a> for this job:</p>
  
  <blockquote>
    <p>bool <strong>SerializeToString</strong>(string* output) const;: serializes the message
    and stores the bytes in the given string. Note that the bytes are
    binary, not text; we only use the string class as a convenient
    container.</p>
  </blockquote>
  
  <p>And say I transfer this data with async_write on the client side:</p>
  
  <pre><code>size_t dataLength = strlen(data);
  
  //writes a certain number of bytes of data to a stream.
  asio::async_write(mSocket,
                        asio::buffer(data, dataLength),
                        std::bind(&amp;Client::writeCallback, this,
                                  std::placeholders::_1,   
                                  std::placeholders::_2)); 
  </code></pre>
  
  <p>How can I read this data on the server side? I don't know how much data I will have to read. Therefore this will not work (length is unknown):</p>
  
  <pre><code> asio::async_read(mSocket,
                       asio::buffer(mResponse, length),
                       std::bind(&amp;Server::readCallback, this,
                                 std::placeholders::_1,
                                 std::placeholders::_2));
  </code></pre>
  
  <p>What is the best way to solve this problem? I could think of two solutions:</p>
  
  <ol>
  <li>Append a 'special' character at the end of <code>data</code> and read until I reach this 'end of data signal'. The problem is, what if this character appears in <code>data</code> somehow? I don't know how Protocoll Buffers serializes my data.</li>
  <li>Send a binary string with <code>size_of_data + data</code> instead of <code>data</code>. But I don't know how to serialize the size in an platform independent way, add it to the binary data and extract it again.</li>
  </ol>
  
  <p>Edit: Maybe I could use this:</p>
  
  <pre><code>    uint64_t length = strlen(data);
      uint64_t nwlength = htonl(length);
      uint8_t len[8];
      len[0] = nwlength &gt;&gt; 56;
      len[1] = nwlength &gt;&gt; 48;
      len[2] = nwlength &gt;&gt; 40;
      len[3] = nwlength &gt;&gt; 32;
      len[4] = nwlength &gt;&gt; 24;
      len[5] = nwlength &gt;&gt; 16;
      len[6] = nwlength &gt;&gt; 8;
      len[7] = nwlength &gt;&gt; 0;
  
      std::string test(len);
  
      mRequest = data;
      mRequest.insert(0, test);
  </code></pre>
  
  <p>and send mRequest to the server? <strong>Any traps or caveats with this code?
  How could I read the length on server side and the content afterwards?</strong>
  Maybe like this:</p>
  
  <pre><code>void Server::readHeader(){
  
      asio::async_read(mSocket,
                       asio::buffer(header, HEADER_LENGTH),
                       std::bind(&amp;Server::readHeaderCallback, this,
                                 std::placeholders::_1,
                                 std::placeholders::_2),
                       asio::transfer_exactly(HEADER_LENGTH));
  }
  
  void Server::readHeaderCallback(const asio::error_code&amp; error,
                                          size_t bytes_transferred){
  
      if(!error &amp;&amp; decodeHeader(header, mResponseLength)){
          //reading header finished, now read the content
          readContent();
      }
      else{
          if(error) std::cout &lt;&lt; "Read failed: " &lt;&lt; error.message() &lt;&lt; "\n";
          else std::cout &lt;&lt; "decodeHeader failed \n";       
      }
  }
  
  void Server::readContent(){
  
      asio::async_read(mSocket,
                       asio::buffer(mResponse, mResponseLength),
                       std::bind(&amp;Server::readContentCallback, this,
                                 std::placeholders::_1,
                                 std::placeholders::_2),
                       asio::transfer_exactly(mResponseLength));
  }
  
  void Server::readContentCallback(const asio::error_code&amp; error,
                                           size_t bytes_transferred){
      if (!error){
         //handle content
      }
      else{
          //@todo remove this cout
          std::cout &lt;&lt; "Read failed: " &lt;&lt; error.message() &lt;&lt; "\n";      
      }
  }
  </code></pre>
  
  <p>Please note that I try to use <code>transfer_exactly</code>. Will this work?</p>