В чем смысл boost:: asio:: placeholders:: bytes Transfer
Что означает boost::asio::placeholders::bytes_transferred
в async_read_until()
? В функции обратного вызова она возвращает меньшее значение, чем streambuf.size()
. streambuf
было ясно до обратного вызова. Подводить итоги,...bytes_transferred
- это не фактическое количество байтов, прошедших через сокет, а меньше. Неужели я все это неправильно понял?
EDIT: я читаю следующий протокол из сокета:
Y43,72,0,,91009802000000603=0000000000000000000
"Y43,"
- это заголовок."Y"
- это тип сообщения."43"
- дополнительные байты к читать","
- разделитель. Заголовок-это до тех пор, пока не встретится первое",".
Мой код для чтения выглядит так:
void handle_write(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::asio::async_read_until(
socket_,
inputStreamBuffer_,
',',
boost::bind(
&client::handle_read1, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
else
{
std::cout << "Write failed: " << error << "n";
}
}
void handle_read1(const boost::system::error_code& error,
size_t bytes_transferred)
{
cout << "bytes_transferred=" << bytes_transferred << endl;
if (!error)
{
cout << "0 size=" << inputStreamBuffer_.size() << endl;
istream is(&inputStreamBuffer_);
char c[1000];
is.read(c,bytes_transferred);
c[bytes_transferred]=0;
for (int i=0;i<bytes_transferred;++i)
{
cout << dec << "c[" << i << "]=" << c[i] << " hex=" << hex << static_cast<int>(c[i]) << "#" << endl;
}
}
else
{
std::cout << "Read failed: " << error << "n";
}
}
Для потока, посланного с другой стороны:
Y43,71,0,,91009802000000595=0000000000000000000
Несколько раз я читал это:
bytes_transferred=4
0 size=47
c[0]=Y hex=59#
c[1]=4 hex=34#
c[2]=3 hex=33#
c[3]=, hex=2c#
Для потока, посланного с другой стороны:
Y43,72,0,,91009802000000603=0000000000000000000
Но в других случаях я читаю это:
bytes_transferred=7
0 size=47
c[0]= hex=0#
c[1]= hex=0#
c[2]= hex=0#
c[3]= hex=0#
c[4]=7 hex=37#
c[5]=2 hex=32#
c[6]=, hex=2c#
Сокет защищен SSL, а клиентские и серверные приложения являются слегка модифицированными примерами из boost_asio / example / ssl/* .
Во втором примере я теряю весь заголовок: (
3 ответа:
Есть четыре перегрузки функции, но давайте просто предположим, что используется первая. Если вы посмотрите на документацию , то вы увидите, что
bytes_transferred
- это количество байт до указанного разделителя и включая его.И далее:
После успешной операции async_read_until streambuf может содержать дополнительные данные за пределами разделителя. Приложение обычно оставляет эти данные в streambuf для последующей операции async_read_until, чтобы исследовать.
Решено. Я передавал
std::string
объектboost::asio::buffer()
, а неstd::string.c_str()
при отправке ответа с сервера.
Как и предполагают документы, вы должны быть в состоянии игнорировать все, что выходит за пределы
bytes_transferred
и просто вызватьasync_read_until
снова.Однако, если вы используете совершенно новую реализацию SSL в ASIO 1.5.3 (которая официально еще не является частью boost), вы можете столкнуться с той же проблемой, что и я (для которой я представил патч):
Http://comments.gmane.org/gmane.comp.lib.boost.asio.user/4803
Не похоже, что вы используете новую версию или сталкиваетесь с той же проблемой, но это то, что нужно знать, если вы столкнулись с некоторыми ограничениями и соблазнились преимуществами новой реализации:
Новая реализация компилируется быстрее, показывает существенно улучшенную производительность и поддерживает пользовательское выделение памяти и вызов обработчика. Он включает в себя новые функции API, такие как проверка сертификатов обратных вызовов и имеет улучшенные отчеты об ошибках. Новая реализация совместима с исходным кодом для большинства применений.