LINUX.ORG.RU

тайм-аут при вызове connect

 , ,


0

1

допустим, программа вызывает connect(), пытаясь приконнектиться к несуществующему/выключенному/зафайерволенному компу. В таком случае connect возвращается с ошибкой где-то через минуту. Где задается этот временной интервал и можно ли его менять?


★★★★★

Делаем сокет неблокирующимся перед connect(2), если connect вернул <0 и errno == EINPROGRESS, засовываем сокет в select/poll/etc с таймаутом и ждём доступности его на запись или указанного истечения времени. Если не таймаут - смотрим на getsockopt(SO_ERROR).

Или я не понял, что требуется?

kemm
()

Это таймаут DNS, скорее всего. По хорошему, вроде никак. Столкнулся с этой проблемой где-то полтора года назад - вменяемого решения не нашел. В итоге сделал какой-то workaround.

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

Если kemm правильно понял, то ниже СИ-функция, которая работает на
Free-Bsd и Centos sizeof(int)=4 и sizeof(int)=8.

//---------------------------- make_socket_ip_1 ------------------------------------

//--- создает неблокирующий соединенный TCP-сокет ---
//  ip_serv    -ip сервера (из номеров и точек)
//  port       -порт сервера
//  ip         -ip локалной привязки (из номеров и точек), можно NULL
//  tmrd       -тайм-аут connect
//  глобальная int err0;  -копия errno
//  глобальная int err;

int make_socket_ip(const char *ip_serv, int port, const char *ip, int tmrd)

{
    int k, len, flags, sd=-1;
    fd_set wrsd;
    struct timeval tv;
    struct sockaddr_in srv_adr, addr;
    in_addr_t  hostAddr;
    in_addr_t  hostAddr1;

    err0=0;
    bzero(&srv_adr,sizeof(srv_adr));
    hostAddr=inet_addr(ip_serv);
    if(hostAddr!=INADDR_NONE)bcopy(&hostAddr,&srv_adr.sin_addr,sizeof(hostAddr));
    else{ err=1; return(-1);}

    srv_adr.sin_port=htons(port);
    srv_adr.sin_family=AF_INET;
    sd=socket(AF_INET,SOCK_STREAM,0);
    if(sd<0){ err0=errno; err=2; return(-2);}
    if(sd >= FD_SETSIZE){ err=3; close(sd); return(-3);}

    //--- далее все ошибки направляются на ERR: для закрытия сокета ---
    if(ip!=NULL){
        hostAddr1=inet_addr(ip);
        if(hostAddr1 == INADDR_NONE){ err=4; goto ERR;}
        bzero(&addr,sizeof(addr));
        bcopy(&hostAddr1,&addr.sin_addr,sizeof(hostAddr1));
        addr.sin_port=htons(0);
        addr.sin_family=AF_INET;
        k=bind(sd, (struct sockaddr *)&addr, sizeof(addr));
        if(k<0){  err0=errno; err=5; goto ERR;}
    }
    flags=fcntl(sd, F_GETFL, 0);
    if(flags<0){ err0=errno; err=6; goto ERR;}
    k=fcntl(sd, F_SETFL, flags | O_NONBLOCK);
    if(k<0){ err0=errno; err=7; goto ERR;}
    k=connect(sd,(struct sockaddr *)&srv_adr, sizeof(srv_adr));
    if(k!=0 && errno != EINPROGRESS){err=8; err0=errno; goto ERR;}
    if (k==0){ goto ret;}   //--- уже соединен ---
    FD_ZERO( &wrsd );
    FD_SET( sd, &wrsd );
    tv.tv_sec = tmrd;
    tv.tv_usec =0;
    k=select(sd+1, NULL, &wrsd, NULL, &tv );
    if(k<0){ err0=errno; err=9; goto ERR;}
	if(k==0){err0=errno; err=10; goto ERR;}

    len=sizeof(err);
    k=getsockopt(sd, SOL_SOCKET, SO_ERROR, &err, &len);
    if(k<0){ err=11; err0=errno; goto ERR;}
    if(err!=0){err0=err; err=12; goto ERR;}

ret:
    return(sd);

ERR:
    close(sd);
    return(-err);
}
oleg_2
()
Ответ на: комментарий от kemm

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

Но меня все таки интересует сабжевый вопрос, можно ли этот временной период как-то уменьшить

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

Да, я протупил =) Почему-то про getaddrinfo подумал...

По сабжу: эта задержка из-за особенностей установки TCP соединения, никаких опций для connect (на подобии SO_RCVTIMEO для recv) не существует. Решается через неблокирующий коннект или костылем в виде запуска connect в отдельном потоке.

kulti ★★
()

Где задается этот временной интервал и можно ли его менять?

В ядре. Можно, смотри комментарий ABW

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