2012-02-17 2 views
2

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

+0

Что вы имеете в виду: * информация о длине кодируется в формате пакета *? Кадрирование протоколов обычно выполняется на уровне приложений, я думаю, вы запутываете себя, думая о пакетах вместо потока данных. –

ответ

1

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

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

я получить размер (m_outbound_data является станд :: строка == сериализованная объект)

//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 раза: первый прочитал 8 байт, чтобы получить размер, а затем прочитать данные в векторе и десериализации в объекте:

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

Я использую эту структуру, чтобы получить данные, вызов читать на 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 

затем называют еще раз перечитал с m_inbound_data на буфер, этот результат чтения именно данные отправленного Во втором handle_read вы Juste должны десериализации данные:

//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 

Надеюсь, что вам помогут!

+0

+1 хороший ответ, вот что я хотел бы предложить. Измените свой протокол, чтобы включить заголовок длины исправления. Если вы не можете изменить свой протокол, укажите это в вопросе. –

1

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

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

+1

Я понимаю, что вам нужна информация о длине, то есть данная. Непонятно указывать эту длину (количество байтов, которые я хочу читать) в API. – Oliver

+0

@ Оставь свой комментарий не имеет смысла. Количество прочитанных байтов хорошо документировано в таких API, как ['boost :: asio :: read'] (http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/reference/read/ overload1.html) –

1

Простой:

boost::asio::read(socket, buffers, boost::asio::transfer_exactly(your_fixed_size)); 
Смежные вопросы