альтернативы std :: string для использования с boost :: asio - PullRequest
19 голосов
/ 09 марта 2011

boost::asio различные read и write функции и методы принимают boost::asio::buffer.Согласно документации буфера , изменяемый std::string не может быть заключен в boost::asio::buffer и, следовательно, не может использоваться для функций read asio.Вероятно, это связано с тем, что std::string не разрешает изменяемый доступ к своему внутреннему буферу (это обсуждалось ранее здесь ).

Это позор, потому что std::stringудобный способ представления изменяемых буферов данных в C ++.Без этого у нас либо останутся массивы POD, boost::array и std::vector<char>.Первые два неудобны с сообщениями переменной длины.std::vector<char> может работать, но это неестественный способ переносить буферы данных вокруг (*)

Вопросы:

  1. Существуют ли другие альтернативы std::string с boost::asio длябуферы чтения?Я что-то здесь упускаю?
  2. Интересно, почему std::vector<char> поддерживается в изменяемом буфере.Это потому, что он гарантирует, что его внутренний буфер является непрерывным в памяти и обеспечивает изменяемый доступ к нему с &vec[0]?

Заранее спасибо


(*) ИМХО.Посмотрите, например, сериализацию protobuf - она ​​предлагает сериализацию в std::string, но не в std::vector<char>, по крайней мере, не в явном виде.


РЕДАКТИРОВАТЬ: В итоге я использовал vector<char> в конце концов.protobuf позволяет сериализовать в vector<char> с помощью вызова SerializeToArray, который принимает указатель (&vec[0] может быть передано туда).

Ответы [ 3 ]

8 голосов
/ 10 марта 2011

Изменчивый доступ к строковому буферу с использованием &str[0] отлично работает во всех известных реализациях, а формулировка будущей стандартизации C ++ 0x делает это официально разрешенным.думать, что std::vector является неестественным представлением для буфера переменной длины.

5 голосов
/ 11 марта 2011

Это ответ на комментарий Элая

Я изначально не упоминал asio :: streambuf в моем вопросе, действительно, потому что мне не было на 100% ясно, как его использовать с фиксированным размеромчитает и asio.Не могли бы вы указать на пример (или добавить один в качестве ответа), показывающий, как читать фрагменты фиксированной длины в std::sstream?

Вот предыдущий ответ об использованииasio::streambuf и Boost.Serialization.Документация asio также содержит пример синхронного чтения:

boost::asio::streambuf b;

// reserve 512 bytes in output sequence
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512);

size_t n = sock.receive(bufs);

// received data is "committed" from output sequence to input sequence
b.commit(n);

std::istream is(&b);
std::string s;
is >> s;
2 голосов
/ 10 марта 2011

1) альтернативы можно найти, проверив функцию asio::buffer(), перегрузки, которые возвращают mutable_buffers_1. более гибкий (но, вероятно, неоптимальный) вариант - asio::streambuf, полезен для (async_)read_until.

если у вас есть протокол полей фиксированного размера, вы можете использовать массив asio::mutable_buffer. например,

using boost::asio;
int i;
short s;
char data[data_size]; // data_size is defined elsewhere
boost::array<asio::mutable_buffer, 3> bufs = {
    asio::buffer(&i, 4), 
    asio::buffer(&s, 2),
    asio::buffer(data, data_size)
};
asio::read(socket, buffer(bufs)); // socket defined elsewhere

2) вы уже ссылались на отличный ответ на этот вопрос: "Как асинхронно читать в std :: string с помощью Boost :: asio?"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...