problem med select()
Jeg har en funktion, der skal connecte en socket med et timeout på etableringen af forbindelsen. Jeg bruger ioctl med FIONBIO (eller fcntl med O_NONBLOCK)til at sætte min socket til non-blocking, hvorefter jeg kalder connect(), sætter socket til blocking-mode igen og venter med select(). Jeg har sat timeout på select til 3 sekunder, men det virker tilsyneladende kun hvis den vært, jeg prøver at connecte til, er i live. Ellers hænger select uendeligt.
Hvad skal jeg gøre for at få select() til at returnere med timeout når værten er kaput?
Jeg kører under RedHat Linux med 2.4.5 kerne. Koden til min funktion er som følger:
int do_connect(int fd, struct sockaddr *remote, socklen_t len, int *err)
{
struct timeval timeout;
int saveflags,ret,back_err;
fd_set fd_w;
int on = 1, off = 0;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if (ioctl(fd, FIONBIO, &on) < 0)
{
perror(\"ioctl1\\n\");
*err = errno;
return -1;
}
/* This will return immediately */
*err=connect(fd,remote,len);
back_err=errno;
if (ioctl(fd, FIONBIO, &off) < 0)
{
perror(\"ioctl2\\n\");
*err = errno;
return -1;
}
/* return unless the connection was successful or the connect is still in progress. */
if(*err<0 && back_err!=EINPROGRESS)
{
perror(\"connect\\n\");
*err=errno;
return -1;
}
FD_ZERO(&fd_w);
FD_SET(fd,&fd_w);
*err=select(fd+1, NULL, &fd_w,NULL, &timeout);
if(*err<0)
{
perror(\"select\\n\");
*err=errno;
return -1;
}
/* 0 means it timeout out & no fds changed */
if(*err==0)
{
close(fd);
*err=ETIMEDOUT;
return -1;
}
/* Get the return code from the connect */
len=sizeof(ret);
*err=getsockopt(fd,SOL_SOCKET,SO_ERROR,&ret,&len);
if(*err<0)
{
perror(\"getsockopt\\n\");
*err=errno;
return -1;
}
/* ret=0 means success, otherwise it contains the errno */
if(ret)
{
*err=ret;
return -1;
}
*err=0;
return 0;
}
