Установите тайм-аут подключения с помощью setsockopt в Linux

Я пишу приложение Linux Qt5/С++, которое пытается подключиться к узлу с помощью QTcpSocket. Я звоню

tcpsocket->connectToHost(address,port,options)

Когда одноранговый узел доступен, он отлично работает и сразу же подключается. Однако, когда одноранговый узел недоступен: при первом вызове вышеуказанного соединение ждет 1 минуту, прежде чем я получу ошибку SocketTimeoutError (5). Затем каждый последующий вызов для подключения может ждать секунду, прежде чем я получу ConnectionRefusedError (0), или может ждать целую минуту (в зависимости от тестируемой системы).

Есть ли setsockopt, который я могу использовать, чтобы сократить время ожидания первоначального подключения?

Я должен указать, что я уже установил некоторые параметры сокета, чтобы быстро уведомить меня о потерянном соединении (см. ниже). Надеюсь, это не вызывает 1-минутную задержку начальной ошибки подключения:

int enableKeepAlive = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
int maxIdle = 5; /* seconds */
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
int count = 3;  // send up to 3 keepalive packets out, then disconnect if no response
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &count, sizeof(count));
int interval = 2;   // send a keepalive packet out every 2 seconds (after the 5 second idle period)
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));

person TSG    schedule 19.09.2014    source источник
comment
Я нашел в Google одну ссылку на setsockopt(socket_handle, SOL_TCP, OPT_CONNECT_TIMEOUT, &option, sizeof(option)) но она не скомпилируется, так как OP_CONNECT_TIMEOUT отсутствует (по крайней мере, не в моих заголовках)   -  person TSG    schedule 19.09.2014


Ответы (1)


Вместо того, чтобы полагаться на setsockopt(), почему бы вам не установить сокет в неблокирующий режим и не выполнить асинхронный connect(). Затем вы заблокируете select(), poll() или любой другой механизм демультиплексирования событий, который вы используете, установив время ожидания по своему желанию. Как только он станет доступным для записи, вы будете знать, что соединение установлено.

person Void    schedule 19.09.2014
comment
Я уже делаю неблокирующее соединение, что приводит к сигналу socketerror. (Используя QT, поэтому нет выбора или опроса). Я понимаю, что я мог бы также запустить отдельный таймер, чтобы истечь за более короткий промежуток времени, но я ищу вариант сокета. - person TSG; 19.09.2014
comment
@GenerationDSystems: кажется странным, что вам нужно установить параметр сокета, чтобы вообще установить тайм-аут неблокирующего подключения. Насколько я понимаю, connectToHost() должен возвращаться немедленно без тайм-аута, и выдать сигнал connected() после установления соединения. Я нашел старое сообщение о проблеме, похожей на вашу собственную, которая предполагает, что это может быть проблема с системой/драйвером. Возникает ли проблема на других платформах? - person Void; 20.09.2014
comment
Я не думаю, что вы понимаете вопрос. Я хочу установить максимальное время, в течение которого сокет будет пытаться подключиться, прежде чем выдавать сигнал об ошибке. На данный момент это 1 минута, мне нужно ‹ 5 секунд - person TSG; 20.09.2014
comment
Ах ладно, моя ошибка. AFAIK, нет стандартного способа сделать это. На какой платформе вы находитесь? Вот один из способов сделать это в Linux, например: sekuda.com/ - person Void; 22.09.2014
comment
См. выше. Я пишу приложение для Linux Qt5/С++. То есть вы говорите, что это нельзя сделать для каждого соединения — это должно влиять только на всю ОС? - person TSG; 23.09.2014
comment
@GenerationDSystems: похоже, вы можете установить количество повторных передач SYN с детализацией сокета с помощью чего-то вроде непереносимого setsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &syn_cnt, sizeof(syn_cnt)) - см. tcp(7) справочная страница, но я не думаю, что время ожидания подключения будет меньше 5 секунд, поскольку установка TCP_SYNCNT на 1, например, даст вам что-то вроде 36 секунд, AFAICT. Я никогда не пробовал это раньше, и только что узнал об этом сам. YMMV. - person Void; 24.09.2014