Альтернативы 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]
может быть передан там).
Ответы
Ответ 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?"