Как следует сбрасывать boost:: asio:: ip:: udp:: socket?

Я прочитал ссылку на повышение asio, прошел через учебник и посмотрел на некоторые из примеров. Тем не менее, я не могу видеть, как сокет должен быть снесен:

  • Должен ли я вызвать метод close(), или это выполняется деструктором сокета?
  • Когда мне нужно вызвать shutdown()
  • Каковы последствия shutdown()? Я знаю, что это "Отключает отправку или получение", но как это делается? Что я могу ожидать, если я отправлю или получаю с помощью сокета после его отключения?
  • Какие ошибки я могу ожидать от close()

Ответ 1

Поскольку это многопрофильный вопрос, я сделаю все возможное, чтобы ответить каждой части на ваше удовлетворение:

1) Это был мой опыт с сокетами ASIO, которые деструктор обрабатывает, закрывая сокет. Однако я занимался только сокетами TCP. Лучший способ проверить это - просто посмотреть на код деструктора, чтобы увидеть, делает ли он что-либо, похожее на закрытие. Я знаю, что код Boost может немного запутаться, поэтому проще всего создать небольшую пробную программу, которая откроет UDP-сокет, а затем уничтожит его. Таким образом, вы можете пройти через код в отладчике, чтобы следовать логике.

Поскольку разработчики Boost учли это для сокетов TCP, мне трудно представить, что они не будут делать то же самое для сокетов UDP.

2) Вызовите shutdown() только в том случае, если вы считаете необходимым предотвратить использование кода в будущем recv и/или send в сокете. Это обычно не требуется, хотя я видел, что он использовался в сокетах TCP, чтобы заставить сокет отправлять RST, когда он закрыт (в отличие от по умолчанию "изящного" выключения, где обрабатываются ожидающие отправки).

3) Вы можете думать о сокетах как о двухканальной форме общения: один для чтения, другой для отправки. Вы можете отключить один из них независимо друг от друга, и вы можете продолжать использовать один канал, когда другой выключается (т.е. Вы все равно можете получить после завершения отправки для отправки и наоборот). Закрытие сокета идентично отключению вызова как для recv, так и для отправки.

Выключение для recv просто не позволяет вашему коду читать больше данных. Если вы попытаетесь сделать это, вы получите ошибку сокета. Аналогичным образом, если другая сторона соединения пытается отправить вам данные, она получит сообщение об ошибке (извините, что снова переключился на мир TCP, но я верю, что RST ответят обратно отправителю).

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

4) Вам обязательно нужно будет проверить свои документы. MSDN даст вам довольно хороший признак, хотя я не знаю, что считаю его авторитетным.

Ответ 2

Из примеров, приведенных на веб-сайте Boost, кажется, что вам просто нужно использовать функцию close(). Например, посмотрите на это:

void connection::stop()
{
  socket_.close();
}

Снято с этого адреса: HTTP-сервер