2013-11-10 3 views
11

Предположим, у меня есть гнездо:Как определить, когда сокет подталкивание TCP разъединяет

std::shared_ptr<tcp::socket> socket(new tcp::socket(acceptor.get_io_service())); 
acceptor.async_accept(*socket, std::bind(handleAccept, this, std::placeholders::_1, socket, std::ref(acceptor))); 

И я хранить weak_ptr к указанной розетки в контейнере. Мне нужно это, потому что я хочу разрешить клиентам запрашивать список других клиентов, чтобы они могли отправлять сообщения друг другу.

clients_.insert(socket); // pseudocode 

Затем я запускаю некоторые операции асинхронных

socket->async_receive(boost::asio::buffer(&(*header), sizeof(Header)) 
    , 0 
    , std::bind(handleReceiveHeader, this, std::placeholders::_1, std::placeholders::_2, header, socket)); 

Как определить, когда соединение закрывается, так что я могу удалить мой сокет из контейнера?

clients_.erase(socket); // pseudocode 

ответ

14

Сокет разъединение TCP обычно сигнализировал в asio ПРОИЗВОДИМОГО eof или connection_reset. Например.

void async_receive(boost::system::error_code const& error, 
        size_t bytes_transferred) 
    { 
    if ((boost::asio::error::eof == error) || 
     (boost::asio::error::connection_reset == error)) 
    { 
     // handle the disconnect. 
    } 
    else 
    { 
     // read the data 
    } 
    } 

Я использую boost::signals2 сигнализировать отключиться хотя вы всегда можете передать указатель на функцию к классу сокета, а затем вызвать это.

Будьте осторожны о вашей розеткой и обратного вызова жизни, см: boost-async-functions-and-shared-ptrs

+2

Список ошибок можно найти здесь: http: // www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/reference/error__basic_errors.html – aCuria

+0

Я обнаружил, что это действительно работает, я получаю сообщение об ошибке «connection_reset». Однако в документации я заметил еще один код ошибки «connection_aborted». Нужно ли обрабатывать этот код ошибки? – aCuria

+0

Это полезная ссылка @aCuria. Другим источником кодов ошибок является файл 'boost/system/error_code.hpp'. Что касается ошибки «connection_aborted», я не видел ее в своих приложениях, но в тестировании также нет вреда. – kenba

1

Есть много вариантов, некоторые из них являются:

  1. Как вы храните weak_ptr в контейнере - это не продлит срок службы сокета, так что, когда ваш обработчик получит boost::asio::error::eof (или любой другой) , он не будет копировать/перемещать shared_ptr, и сокет будет удален (если у вас нет других shared_ptr s к нему). Итак, вы можете сделать что-то вроде: if(socket.expired()) clients_.erase(socket);

  2. Проверьте код ошибки в вашем обработчике - он укажет, когда соединение будет закрыто. Используя эту информацию - вы можете позвонить clients_.erase из самого обработчика.

Could you give an example of #2?

Это будет что-то вроде:

socket->async_receive 
(
    boost::asio::buffer(&(*header), sizeof(Header)), 0, 
    [=, &clients_](const system::error_code& error, size_t bytes_transferred) 
    { 
     if(error) // or some specific code 
     { 
      clients_.erase(socket); // pseudocode 
     } 
     else 
     { 
      // continue, launch new operation, etc 
     } 
    } 
); 
+0

Не могли бы вы привести пример # 2? – aCuria

+0

@aCuria Добавлен пример. –

+0

Я не думаю, что я должен удалить какую-либо ошибку, однако быстрый поиск в Google, похоже, не вызывает список кодов ошибок специально для async_receive. – aCuria

Смежные вопросы