Подтвердить что ты не робот

Альтернативы std::string для использования с boost:: asio

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

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

Вопросы:

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

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


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


EDIT: В конце концов я использовал vector<char>. protobuf разрешает сериализацию в vector<char> посредством вызова SerializeToArray, который принимает указатель (&vec[0] может быть передан там).

4b9b3361

Ответ 1

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

Я не упоминал 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

Возможность доступа к строковым буферам с использованием &str[0] отлично работает во всех известных реализациях, и формулировка предстоящих стандартов С++ 0x делает его официально разрешенным.

Тем не менее, я думаю, вы с ума сочли, что std::vector является неестественным представлением для буфера переменной длины.

Ответ 3

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?"