При подключении к недоступному в данный момент урлу скрипт на этапе connect() очень долго висит, а потом вылетает ничего не говоря
...
sock=socket(AF_INET, SOCK_STREAM, 0);
hn=gethostbyname(host);
memcpy(&ssin.sin_addr,hn->h_addr_list[0], hn->h_length);
ssin.sin_family= hn->h_addrtype;
ssin.sin_port= htons((u_short)port);
connect(sock,(struct sockaddr *) &ssin,sizeof(ssin));
send(sock,(char *)request,strlen(request),0);
...
Можно ли сделать и как, что по таймауту (напр. 30 сек) завершалось выполнение connect() и программа не вылетала?
Проблема Socket на С
Модератор: Модераторы разделов
-
elide
- Бывший модератор
- Сообщения: 2421
- Статус: Übermensch
- ОС: лялих
Re: Проблема Socket на С
используй NONBLOCK сокеты и select.
кстати, про то, что у функций есть возвращаемое значение, тебе в школе не рассказывали?
кстати, про то, что у функций есть возвращаемое значение, тебе в школе не рассказывали?
слава роботам!
-
Zloixxx
- Сообщения: 10
Re: Проблема Socket на С
про возвращаемые значения я знаю
долго ждет и вылетает на этом моменте connect(sock,(struct sockaddr *) &ssin,sizeof(ssin));
вот и интересно можноли чтобы по таймауту это операция прекращалась
-
BlackStar
- Сообщения: 1338
- Статус: We are all Kosh
- ОС: Fedora 10
Re: Проблема Socket на С
Она и прекращается по таймауту, смотри в сторону setsockopt и параметров SO_RCVTIMEO и SO_SNDTIMEO.
man 7 socket
man 2 setsockopt
man 7 socket
man 2 setsockopt
LightLang Team
-
elide
- Бывший модератор
- Сообщения: 2421
- Статус: Übermensch
- ОС: лялих
Re: Проблема Socket на С
это не есть гут. слишком непортабельно.SO_RCVTIMEO и SO_SNDTIMEO
если я правильно помню, то POSIX 1003.1g draft 6.4 вообще описывал эти опции как read-only.
в draft 6.6 они уже не read-only, но стоит пометка "Note that not all implementations allow this option to be set."
т.е. вообще её использовать можно, но ну его нафиг.
правильно эта задача решается именно через неблокирующие сокеты и поллинг.
слава роботам!
-
Zloixxx
- Сообщения: 10
-
MedVed
- Сообщения: 112
Re: Проблема Socket на С
Посмотри у Стивенса "Разработка сетевых приложений", глава 15, если память не изменяет, - там есть код функции connect с таймаутом.
Основная идея - сделать сокет неблокирующим, а потом ждать в select'е нужное время.
Что-то вроде этого (на вскидку, не факт, что будет работать):
Основная идея - сделать сокет неблокирующим, а потом ждать в select'е нужное время.
Что-то вроде этого (на вскидку, не факт, что будет работать):
Код: Выделить всё
int timed_connect(int sock, const sockaddr* addr, int len, int timeout)
{
int flags = ::fcntl(sock, F_GETFL, 0);
::fcntl(sock, F_SETFL, flags|O_NONBLOCK);
int rc = 0;
if ( (rc = ::connect(sock, addr, len)) < 0 )
if (EINPROGRESS != errno) return -1; // Ошибка!
if (rc == 0) return 0; // Нормально - соединились!
// Не соединились - будем ждать
fd_set fdsRead, fdsWrite;
FD_ZERO(&fdsRead);
FD_ZERO(&fdsWrite);
FD_SET(sock, &fdsRead);
FD_SET(sock, &fdsWrite);
struct timeval wait_time;
wait_time.tv_sec = timeout;
wait_time.tv_usec = 0;
if ( (rc = ::select(sock+1, &fdsRead, &fdsWrite, NULL, &wait_time) == 0)
{
::close(sock);
errno = ETIMEDOUT;
return -1;
}
if ( FD_ISSET(sock, &fdsRead) || FD_ISSET(sock, &fdsWrite) )
{
// Здесь по-идее должен быть код проверки для Solaris, но я его не помню :)
::fcntl(sock, F_SETFL, flags);
return 0;
}
::close(sock);
return -1;
}МСВС 3.0/Linux Mandrake 8.0