#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 мс поступит сообщение о недоступности порта ICMP2. Возможно ли, что вы также выполнили брандмауэр icmp?
3. Нет, потому что, если я ОТБРОШУ запрос SYN, select () будет ждать вечно.. но посмотрите:
REJECT tcp -- anywhere anywhere tcp dpt:6379 reject-with icmp-port-unreachable
и все политики ПРИНЯТЫ