LINUX.ORG.RU

Таймаут для connect()


0

0

Как задать ф-ии connect() таймаут, а то если хост не доступен приходится долго ждать.

std::string finish_msg = strm_msg.str();

char buf[5555]; struct sockaddr_in addr; int sock; sock = socket ( AF_INET, SOCK_STREAM, 0 ); //fcntl(sock, F_SETFL, O_NONBLOCK);

if ( sock < 0 ) { perror ( "socket" ); exit ( 1 ); } //75.126.149.34 addr.sin_family = AF_INET; addr.sin_port = htons ( 80 ); addr.sin_addr.s_addr = inet_addr ( "75.12.149.34" ); std::cout << connect ( sock, ( struct sockaddr * ) &addr, sizeof ( addr ) ) << std::endl;

send ( sock, finish_msg.c_str(), finish_msg.size(), 0 ); recv ( sock, buf, sizeof ( buf ), 0 );

Вот же:

> //fcntl(sock, F_SETFL, O_NONBLOCK);


Просто переводишь его в неблокирующий режим и после вызова connect ждёшь пока сокет за коннектится с помощью select или poll. А у select и poll можно указывать таймаут.

Ещё вроде можно указать таймаут с помощью setsockopt. В этом случае можно использовать и обычные блокирующие сокеты. Но я точно не помню - читай документацию.

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

В общем мне нужно проверить список IP (прокси) на валидность. Допустим если за 2-3 секунды соедениться не удалось, то забить на этот IP и перейти к проверке следущего. Что в этом случае лучше всего использовать?

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

> В общем мне нужно проверить список IP (прокси) на валидность. Допустим если за 2-3 секунды соедениться не удалось, то забить на этот IP и перейти к проверке следущего. Что в этом случае лучше всего использовать?

Я бы вообще написал маленький шелл-скрипт с использованием netcat. Типа такого:

TIMEOUT=3
PORT=8080
for i in proxy1.org proxy2.com proxy3.net; do
    if nc -z -w "${TIMEOUT}" "${i}" "${PORT}"; then
        echo "${i} - valid proxy"
    else
        echo "${i} - invalid proxy"
    fi
done

А если сильно надо на C/C++, то можно посмотреть как таймаут реализован в netcat.

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

Так после проверки прокси на валидность, в случае если прокси жив, мне через него нужно будет передать http запрос на сайт, а если прокси не доступен, то перейти к проверки следущего (список большой :)).

Короче главная задача моей программки - общаться с сервером по протоколу http через прокси. И когда попадается мёртвый/тугой прокси, приходится ждать 75 сек.

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


как уже отметили выше, connect + select полностью решат проблемы отца русской демократии.

// wbr

klalafuda ★☆☆
()

Вот попытался написать, только оно не работает. И вообще я не могу понять как оно должно работать :) Как мне получить ответ от сервера? По идее recv ( sock, buf, sizeof ( buf ), 0 ) - должен записать его в buf, но этого не происходит :(

fd_set mst; struct timeval tv;

char buf[5555]; struct sockaddr_in addr; int sock; sock = socket ( AF_INET, SOCK_STREAM, 0 ); fcntl(sock, F_SETFL, O_NONBLOCK); if ( sock < 0 ) { perror ( "socket" ); exit ( 1 ); }

addr.sin_family = AF_INET; addr.sin_port = htons ( 80 ); addr.sin_addr.s_addr = inet_addr ( "75.126.149.34" ); if ( connect ( sock, ( struct sockaddr * ) &addr, sizeof ( addr ) ) < 0 ) { tv.tv_sec = 5; tv.tv_usec = 0;

//FD_ZERO(&mst); FD_SET(sock, &mst);

if(select(sock + 1, NULL, &mst, NULL, &tv ) < 0) { std::cout << "hi" << std::endl; }

perror ( "select" ); exit ( 2 ); send ( sock, finish_msg.c_str(), finish_msg.size(), 0 ); recv ( sock, buf, sizeof ( buf ), 0 ); }

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

> С английским проблемы :(

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

// wbr

klalafuda ★☆☆
()

/me ушел учить английский. Вернётся лет через *надцать и продолжит учить сокеты...

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

Пример:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>

const char *const query =
		"GET / HTTP/1.1\n"
		"Host: google.com\n"
		"\n";

static void die(const char *msg)
{
	fprintf(stderr, "ERROR: %s\n", msg);
	exit(EXIT_FAILURE);
}

int main()
{
	int			s;
	struct sockaddr_in	addr;
	fd_set			fds;
	struct timeval		tv;
	int			ret;
	socklen_t		len;
	ssize_t			data_len;
	char			buf[128];

	s = socket(AF_INET, SOCK_STREAM, 0);
	if (s == -1)
		die("socket()");
	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
		die("fcntl()");

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(80);
	addr.sin_addr.s_addr = inet_addr("74.125.45.100"); /* google.com */
	if (connect(s, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
		if (errno != EINPROGRESS)
			die("connect()");
	}

	/* Wait for connection. */
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	FD_ZERO(&fds);
	FD_SET(s, &fds);
	ret = select(s + 1, NULL, &fds, NULL, &tv);
	if (!ret)
		die("Timeout exceeded");
	else if (ret == -1)
		die("select() #1");
	len = sizeof(ret);
	if (getsockopt(s, SOL_SOCKET, SO_ERROR, &ret, &len) == -1)
		die("getsockopt()");
	if (ret)
		die("Can't connect to server.");

	data_len = strlen(query);
	if (write(s, query, (size_t) data_len) != data_len)
		die("write()");

	for (;;) {
		/* Wait for data. */
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		FD_ZERO(&fds);
		FD_SET(s, &fds);
		ret = select(s + 1, &fds, NULL, NULL, &tv);
		if (!ret)
			die("Timeout exceeded");
		else if (ret == -1)
			die("select() #2");

		data_len = read(s, buf, sizeof(buf));
		if (!data_len)
			break; /* EOF */
		else if (data_len == -1)
			die("read()");

		if (fwrite(buf, (size_t) data_len, 1, stdout) != 1)
			die("fwrite()");
	}

	return 0;
}

P.S. Вроде работает, но тем не менее могут быть ошибки =).

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

ууууух, СПАСИБО! Я уже и не надеялся, что кто нить поможет. Большое спасибо :) Есть же добрые люди )

byte555
() автор топика

Если на плюсах пишешь, то возьми boost:asio (или просто asio без boost), не мучайся.

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

> Если на плюсах пишешь, то возьми boost:asio (или просто asio без boost), не мучайся.

asio? ммм.. нет, спасибо, уж лучше вы к нам (c).. :)

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от mv

> Есть негативный опыт?

ну не то чтобы негативный... скорее - никакой. на первый взгляд всё вроде как красиво. но как только начинаешь рисовать что-то более-менее разлапистое натыкаешься на то, что объём кода растёт по экспоненте. опять же, документация конечно доступна, но её содержимое явно не дотягивает до желаемого. когда кто что бросает? какие side effects? и тд и тп. лично у меня всё время присутствовало стойкое ощущение прогулки по минному полю :-/

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> ну не то чтобы негативный... скорее - никакой. на первый взгляд всё вроде как красиво. но как только начинаешь рисовать что-то более-менее разлапистое натыкаешься на то, что объём кода растёт по экспоненте. опять же, документация конечно доступна, но её содержимое явно не дотягивает до желаемого. когда кто что бросает? какие side effects? и тд и тп. лично у меня всё время присутствовало стойкое ощущение прогулки по минному полю :-/

резюмируя: да, в бусте есть asio. да, она в принципе работает. по крайней мере под линуксом. но лично я не стал бы советовать её как панацею налево и направо. по крайней мере в том состоянии, в котором она находилась полгода назад или чуть более. впрочем, поскольку проект развивается достаточно динамично, не исключаю, что сегодня ту же документацию уже и допилили до человечего вида. не знаю, не заглядывал.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> но как только начинаешь рисовать что-то более-менее разлапистое натыкаешься на то, что объём кода растёт по экспоненте.

А это точно проблема asio, а не недостаток проектирования? На плюсах ведь как только от генерального плана отклоняешься (или генеральный план не продуман), то всё, амба: тонны костылей и подпорок.

> лично у меня всё время присутствовало стойкое ощущение прогулки по минному полю :-/


Лично у меня возникает чёткое ощущение велосипедизма и закапывания мин и последующего хождения по ним, когда люди пишут с нуля очередную сетевую прослойку.

А asio малобажный продукт (к тому же, реализация headers-only). Я его в 3-х проектах использовал, глюков не видел. В одном проекте кол-во инсталляций ещё при мне было полторы тысячи,
сейчас ещё больше, Соответственно, малейший баг моментально на пачке машин высвечивался. Вот скрытые косяки в самодельных прослойках вылазили время от времени, а asio просто работало. Другой проект делал асинхронным, с одним реактором на всё (что-то типа гейта, которому smp не в тему было). Код получился компактным, никаких мьютексов, и нагрузку бешенную держит.

Собственно, из "проблем" в asio могу только отметить изменение интерфейсов в последующих версиях. Но становится только лучше.

Я что попало не советую :)

mv ★★★★★
()

я знаю 3 способа:

сonnect+select

setsockopt()

SIGALRM + alarm

все они рабочие. но какой из них самый переносимый - хз :)

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