Тестирование на закрытое гнездо - PullRequest
10 голосов
/ 14 марта 2010

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

Одним из предположений здесь является то, что сокет, если он закрыт, был изящно закрыт партнером сразу после его последней записи / отправки. Фактические ошибки, такие как преждевременное закрытие, рассматриваются в другом месте кода.

Если сокет все еще открыт, будет 0 или более байтовых данных, которые я на самом деле не хочу извлекать из буфера сокетов.

Я думал, что мог бы позвонить int ret = recv(sockfd, buf, 1, MSG_DONTWAIT | MSG_PEEK);, чтобы определить, подключен ли сокет. Если он подключен, но в буфере нет данных, я получу возврат -1 с errno == EAGAIN и верну sockfd для повторного использования. Если это было изящно закрыто узлом, я получу ret == 0 и открою новое соединение.

Я проверял это, и , кажется, работает. Тем не менее, я подозреваю, что есть небольшое окно между тем, когда я получаю последний бит моих данных и когда приходит одноранговый узел FIN, в котором я могу получить ложноположительный результат EAGAIN из своего теста recv.

Это меня укусит, или есть лучший способ сделать это?

Ответы [ 3 ]

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

ОК, поэтому я запустил еще несколько тестов, и это то, что я нашел.

Я настроил мой клиент на отправку HTTP/1.1 Connection: close сообщений на сервер, в результате чего сервер закрывается после последней записи данных. Когда мой клиент закончил чтение данных из транзакции GET, он проверил бы сокет, чтобы увидеть, был ли он все еще открыт, используя вышеупомянутый метод, и затем попытался бы выполнить другой GET.

Я обнаружил, что примерно в 30% случаев мой тест будет выполняться до того, как FIN сервера поступит, что приведет к ложным срабатываниям и сбоям в работе.

Вероятно, единственный способ сделать это достаточно надежным, скажем, около 99%, это ввести искусственные задержки, связанные с задержкой соединения между последним чтением и попыткой повторного использования сокета, однако это в значительной степени снизит производительность.

Итак, я должен заключить, что, хотя этот инструмент полезен, он только незначительно.

0 голосов
/ 14 марта 2010

(слегка "не по теме", извините). Возможно эта дискуссия может быть полезна четырем вам. Он по-прежнему не отвечает на вопрос «FIN», но может помочь вам более легко реагировать на отключение узла во время отправки вашей программы.

Пока

0 голосов
/ 14 марта 2010

Ты контролируешь другой конец? Самый надежный способ выполнить «чистое» отключение сокета - это отправить на другой конец какое-то «прощальное» сообщение.

...