Boost.Asio: операция async_read отменена - PullRequest
15 голосов
/ 13 октября 2010

Еще один в продолжающейся саге о себе против Boost.Asio ...

У меня есть простой асинхронный клиент и сервер, которые используют async_write и async_read для связи. Клиент может успешно записывать байты в сокет, но сервер их никогда не видит; мой обработчик чтения на сервере завершается с ошибкой «Операция отменена».

Я склонен полагать, что это может быть проблема синхронизации с клиентом, записывающим данные после сервер попытался прочитать их и не смог, но я бы подумал, что данные будут ждать сокет в любом случае (если сокет не был закрыт в это время).

Чтобы проверить это, я просто повторно запустил операцию чтения в обработчике ошибок, т.е.

read_handler()
{
    if (!error) {
        /* bytes read */
    } else {
        async_read(socket, buffer, read_handler)
    }
}

Но все, что меня заставило, это ошибка в pthread_mutex_lock через звонок async_receive.

Может ли кто-нибудь указать мне какую-либо соответствующую информацию (или, еще лучше, точно сказать, что я делаю неправильно;))?

ОБНОВЛЕНИЕ : сервер и клиент основаны на примере сервера чата в документах Asio, при этом клиент и сервер работают под одним и тем же процессом (может ли это быть проблемой? оба используют один и тот же io_service ...); как асинхронный, так и использующий Boost 1.44.0. Я работаю над OS X, но это также воспроизводимо и в Linux.

ОБНОВЛЕНИЕ II : моя догадка была правильной, и если серверу и клиенту предоставлены отдельные объекты io_service, async_read видит байты в сокете. Это по-прежнему дает segfault в boost::asio::detail::kqueue_reactor::post_immediate_completion, который, кажется, происходит от io_service.run(). Прежде чем идти дальше, правильно ли использовать отдельные объекты io_service?

1 Ответ

29 голосов
/ 27 июля 2012

Операция отменена (код ошибки operation_aborted) отправляется, когда сокет закрыт или отменен.

Скорее всего, ваше соединение каким-то образом выходит за рамки.

Возможнокак это случилось со мной, вы забыли присоединить async_handlers к указателю shared_from_this () .Т.е. вы должны прикреплять свои обработчики так:

async_read(m_socket,
           boost::asio::buffer((void*)m_buffer, m_header_size),
           boost::bind(&TcpConnection::handleRead, 
           shared_from_this(),
           boost::asio::placeholders::error,
           boost::asio::placeholders::bytes_transferred));

И НЕ вот так:

async_read(m_socket,
           boost::asio::buffer((void*)m_buffer, m_header_size),
           boost::bind(&TcpConnection::handleRead, 
           this, //<- This will go out of scope and the socket will be closed
           boost::asio::placeholders::error,
           boost::asio::placeholders::bytes_transferred));
...