Как обнаружить закрытое соединение на сокете без блокирующего вызова в boost asio - PullRequest
0 голосов
/ 06 июня 2019

Я написал схему связи tcp с использованием boost asio, и она работает вполне нормально, если я использую отдельный поток для io_service::run().Тем не менее, коммуникатор также должен использоваться как часть параллельной MPI-программы (пожалуйста, не задавайте вопросов), где разветвление и многопоточность не являются хорошей идеей и могут быть недопустимы.

Для этого коммуникатор имеетфункция work(), которая вызывает io_service::run_one.Теперь, если я напрямую использую async_read, будет блокироваться вызов run_one до тех пор, пока что-то не будет прочитано или не произойдет ошибка.Итак, я написал функцию check_available, показанную ниже, которая сначала проверяет, есть ли что-то в сокете, прежде чем вызывать async_read в моей функции read_message_header.

. Это также работает гладко, пока узел не закроет соединение.К сожалению, socket::available(error), похоже, не помечает это как ошибку eof, как в случае async_read, и возвращает 0 как количество доступных байтов, так что read_message_header никогда не вызывается, что затем обнаружитВФ.Также проверка socket::is_open() не сработала для этой цели, потому что закрыты только сокеты однорангового узла, а не получающий сокет в этом случае.

void TCPConnection::check_availble() {
    if(! socket_.is_open()) {
        handle_read_error(boost::asio::error::eof);
    }
    boost::system::error_code error;
    size_t nbytes=socket_.available(error); // does not detect the eof
    if(error)
        handle_read_error(error);
    if(nbytes>0)
        read_message_header();
    else
        socket_.get_io_service().post(
                boost::bind(
                        &TCPConnection::check_availble,
                        shared_from_this()
                )
        );
}

Есть ли способ обнаружить eof без каких-либо блокирующих вызовов?

1 Ответ

0 голосов
/ 24 июня 2019

У меня есть пара замечаний:

, который вызывает io_service :: run_one. Теперь, если я напрямую использую async_read, это будет блокировать вызов run_one, пока что-то не будет прочитано или возникает ошибка

Вы можете легко подорвать это поведение блокировки, создав поддельный объект work<> и поместив его в очередь io_service, поэтому, пока есть обработчики для выполнения, опрос не будет ждать каких-либо событий: просто немедленно вернитесь .

говоря о size_t nbytes=socket_.available(error);; avilable() возвращает количество байтов, доступных для чтения (может быть без блокировки), и, как указано в комментарии: возможно, вам нужно прочитать готовые байты, чтобы увидеть EOF, но avilable() не имеет к этому никакого отношения .

...