Как прочитать пакет фиксированного размера, используя boost asio? - PullRequest
2 голосов
/ 18 февраля 2012

Я делаю синхронное чтение / запись с использованием boost-asio.Данные поступают в двоичном формате, без границ, информация о длине кодируется в формате пакета.Поэтому важно читать с указанным размером.Может ли ip::tcp::iostream сделать это?Может кто-нибудь привести пример?Спасибо.

Ответы [ 3 ]

1 голос
/ 18 февраля 2012

Я работаю над программой, которая отправляет разные данные разного размера.Я использую фиксированный заголовок из 8 байтов для кодирования размера, затем добавляю данные:

 enum { header_length = 8 }; //const header length

Я получаю размер (m_outbound_data является std :: string == сериализованным объектом)

//give header length    
std::ostringstream header_stream
header_stream << std::setw(header_length) //set a field padding for header  
              << std::hex                 //set next val to hexadecimal
              << m_data_out.m_outbound_data.size(); //write size in hexa

m_data_out.m_outbound_header = header_stream.str(); //m_outbound_head == size in hexa in a std::string

      //m_outbound_header = [ 8 byte size ] 
      //m_outbound_data = [ serialized data ]

      //write all data in the std::vector and send it
      std::vector<boost::asio::const_buffer> buffer;
      buffer.push_back(boost::asio::buffer(m_data_out.m_outbound_header));
      buffer.push_back(boost::asio::buffer(m_data_out.m_outbound_data));

А для чтения вам нужно прочитать в 2 раза: 1-е чтение 8 байт, чтобы получить размер, затем чтение данных в векторе и десериализация в объект:

 struct network_data_in {   
  char m_inbound_header[header_length]; //size of data to read  
  std::vector<char> m_inbound_data; // read data    
};

Я используюэта структура для получения данных, вызовите read для m_inbound_header, чтобы сначала заполнить буфер размером, затем, в дескрипторе:

//get size of data
std::istringstream is(std::string(m_data_in.m_inbound_header, header_length));
std::size_t m_inbound_datasize = 0;
is >> std::hex >> m_inbound_datasize;
m_data_in.m_inbound_data.resize(m_inbound_datasize); //resize the vector

, затем снова вызвать read с m_inbound_data в буфере, этот результат чтения точноотправка данных Во втором дескрипторе handle_read вы должны десериализовать данные:

//extract data
std::string archive_data (&(m_data_in.m_inbound_data[0]),m_data_in.m_inbound_data.size());
std::istringstream archive_stream(archive_data);
boost::archive::text_iarchive archive(archive_stream);
archive >> t; //deserialize

Надеюсь, что это поможет вам!

1 голос
/ 09 февраля 2016

Simple:

boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size));
1 голос
/ 18 февраля 2012

TCP - это потоковый протокол. Это означает, что все, что вы читаете, является просто потоком байтов. Давайте рассмотрим пример: у вас есть сообщение фиксированного размера, и вы отправляете его по TCP. Как программа на другом конце может прочитать все сообщение? Есть два способа, один из них - окружить ваше сообщение контрольными символами (например, STX в начале и ETX в конце). В начале программа отбрасывает любые символы до STX, а затем считывает любые другие символы в буфер сообщений, пока не встретится ETX.

Другим способом является кодирование длины сообщения в заголовке фиксированного размера (что, по-видимому, является вашим случаем). Поэтому лучшее, что вы можете сделать, - это найти способ прочитать длину сообщения, разобрать его и прочитать остальные байты соответственно.

...