Безопасно ли уничтожать объект сокета, когда в boost.ASIO может выполняться asyn_read? - PullRequest
3 голосов
/ 03 марта 2010

В следующем коде:

tcp::socket socket(io_service);
tcp::endpoint ep(boost::asio::ip::address::from_string(addr), i);


socket.async_connect(ep, &connect_handler);

socket.close();

Правильно ли закрывать объект сокета, или я должен закрывать его только в connect_handler(), прибегая к shared_ptr для продления срока службы объекта сокета? Спасибо.

Ответы [ 3 ]

3 голосов
/ 24 марта 2010

Закрытие сокета не является большой проблемой, но уничтожение и освобождение сокета. Один из способов справиться с этим - просто убедиться, что сокет переживает io_service, где выполняется работа. Другими словами, вы просто не должны удалять его до тех пор, пока io_service не выйдет. Очевидно, что это не сработает в любой ситуации.

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

Между тем ваши функторы обработчика должны обрабатывать все возможные ошибки, в том числе и разрушаемое соединение.

1 голос
/ 24 марта 2010

Как уже ответил Чила, безопасно закрывать розетку в любое время. Если у рассматриваемого сокета в то время была ожидающая операция, будет вызван обработчик / обратный вызов, чтобы уведомить вас об отмене операции. Вот где появляется connection_aborted.

Что касается вашего вопроса о shared_ptr, я считаю большой победой, если у вас есть другой поток или другие объекты, ссылающиеся на ваши сокеты, однако во многих случаях это не требуется. Все, что вам нужно сделать, это динамически распределить их и освободить, когда они больше не нужны. Конечно, если у вас есть другие объекты или потоки, ссылающиеся на ваш сокет, вы должны обновить их до удаления / dealloc. Это позволяет избежать недопустимого доступа к памяти, поскольку указанный ими объект больше не существует (см. Висячий указатель).

1 голос
/ 09 марта 2010

Это безопасно. Обработчик connect_handler даст вам ec == boost :: asio :: error :: connection_aborted. Конечно, вам нужно выполнить io_service.run () для вызова обработчика.

...