LINUX.ORG.RU

connect() tсp timeout


0

0

У пишу небольшую программку, которая раз в две минуты пытается установить tcp-соединение с рядом стоящим компом. По задумке, если соединение не удалось, то нужно перезапустить один из сервисов. Проблема в том, что когда рядом стоящий компутер перегружается или из него выдернули сеть, вызов connect() блокирует выполнение программы(и следовательно таймера) на время tcp-таймаута. Можно как-то явно указать connect'у таймаут на установление соединение(например, послали SYN, если в течение 10 секунд не приходит SYN,ACK, то connect вернет -1)?. Или подскажите какой-нибудь другой алгоритм(может нужно connect пустить в отдельном потоке, а в основном пустить еще один таймер, который по истечении 10 секунд застрелит поток, где выполняется connect)? Может лучше не создавать tcp-сессию, а пускать icmp echo request и ждать 10 секунд icmp echo reply (тогда ткните в пример как это делается на Си)? Короче, я никак не пойму с какого конца за эту задачу браться.


ping или udp

а tcp гарантирует доставку, поэтому и таймаут

если пофиг на быстродействие, то

#!/bin/bash

SERVER=localhost
if ( ping -c 5 $SERVER | grep " 0 received" ); then
  echo "DOWN"
else
  echo "UP"
fi

theserg ★★★
()

Это можно сделать прерывая системный вызов сигналом по таймеру, либо использовать неблокируемый сокет с ожиданием готовности к записи в select/poll/epoll и последующей проверкой ошибки в getsockopt.

icmp-ping не проверит работоспособность программы-сервера, только живость сетевой подсистемы ядра и кабель

Dr_ZLO
()

только одно можно посоветовать в данном случае - читать
хорошую книгу по сетевому программированию, желательно в *nix.
обычно в первых главах объясняется почему да как.

anonymous
()
Ответ на: комментарий от anonymous

мало того, на этом форуме, минимум раз 10 это обсуждалось

anonymous
()
Ответ на: комментарий от anonymous

спасибо за советы. то что книжку читать надо я понял, этим и займусь. а пока в качестве временной меры засуну шелл-скрипт с пингом, который посоветовал theserg в cron.

anonymous
()
Ответ на: комментарий от Chumka

Тоже вариант, но в моем man 3p setsockopt написано "Note that not all implementations allow this option to be set". Возможно непереносимо, хотя в линуксе работает.

Dr_ZLO
()

Вот тебе небольшей пример как это делается:

int
connect_timeout (int fd, struct sockaddr *r_addr, int sec)
{
	struct sockaddr remote_addr;
	socklen_t sock_len = 0;
	int retval = 0;
	
	if (sec > 0)
		activate_nonblock(fd);    // O_NONBLOCK
	
	sock_len = sizeof(remote_addr);
	retval = connect(fd, r_addr, sock_len);
	
	if (retval < 0 && errno == EINPROGRESS) {
		struct timeval timeout;
		fd_set r_fd;
		fd_set w_fd;
		
		FD_ZERO(&r_fd);
		FD_SET(fd, &r_fd);
		
		w_fd = r_fd;
		timeout.tv_sec = sec;
		timeout.tv_usec = 0;
		
		do {
		    retval = select(fd + 1, &r_fd, &w_fd,
                    NULL, &timeout);
		} while (retval < 0 && errno == EINTR);
		
		if (retval > 0) {
			socklen_t sock_len = 0;
			int sockopt = 0;
			
			if (FD_ISSET(fd, &r_fd) || (FD_ISSET(fd, &w_fd))) {
				sock_len = sizeof(retval);
                        sockopt = getsockopt(fd, SOL_SOCKET,
                            SO_ERROR, &retval, &sock_len);
				
				if (sockopt != 0 || retval)
					retval = -1;
			} else {
				retval = -1;
			}			
			
		} else if (retval == 0) {
			retval = -1;
		} else {
			retval = -1;
		}
	}
	
	if (sec > 0)
		deactivate_nonblock(fd);
	
	return retval;
}

--
Uladzislau Rezki

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.