тайм-аут select () в 3 секунды даже при недоступности порта ICMP

#c #network-programming #select-function

#c #сетевое программирование #select-функция

Вопрос:

Когда я пытаюсь подключиться к серверу с неблокирующим сокетом (чтобы я мог использовать select () с параметром timeout), я понял, что при подключении к порту, который заблокирован iptables с помощью -j REJECT, select () ожидает до параметра timeout, но максимум 3 секунды .. не имеет значения, что пакет недоступности порта ICMP действительно быстрый.

 fcntl(sockfd, F_SETFL, O_NONBLOCK);
connect(sockfd,(struct sockaddr *) amp;serv_addr,sizeof(serv_addr));
if (select(sockfd   1, NULL, amp;fdset, NULL, NULL) == 1) {...}
  

В приведенном выше примере select () блокируется до 3 секунд, если соединение переходит на localhost: 1234 и порт блокируется, как описано выше.

Кто-нибудь знает, почему этот тайм-аут в 3 секунды приводит к получению сообщения «отказано в подключении»? Как я мог это настроить (потому что порт ICMP стал недоступен через 0,02 мс)?

Ответ №1:

Сокет станет «доступным для записи» только в случае connect успешного выполнения. Если вы также хотите select вернуться при сбое, вам также следует проверить состояние «ошибка / исключение» в сокете, т. е. передать set в качестве третьего fd_set * аргумента select тоже.

Комментарии:

1. подключение всегда выполняется успешно (из-за O_NONBLOCK) и блокируется в блоке select () .. но, чтобы быть уверенным: FD_ZERO(amp;rfdset); FD_ZERO(amp;wfdset); FD_ZERO(amp;efdset); FD_SET(sockfd, amp;rfdset); FD_SET(sockfd, amp;wfdset); FD_SET(sockfd, amp;efdset); if (select(sockfd 1, amp;rfdset, amp;wfdset, amp;efdset, NULL) == 1) {} это также заблокирует 3 секунды, даже если через 0,02 мс поступит сообщение о недоступности порта ICMP

2. Возможно ли, что вы также выполнили брандмауэр icmp?

3. Нет, потому что, если я ОТБРОШУ запрос SYN, select () будет ждать вечно.. но посмотрите: REJECT tcp -- anywhere anywhere tcp dpt:6379 reject-with icmp-port-unreachable и все политики ПРИНЯТЫ