LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   connect() with timeout (http://www.linuxquestions.org/questions/programming-9/connect-with-timeout-494426/)

nodger 10-21-2006 03:19 PM

connect() with timeout
 
Im trying to put a timeout on a connect call, and it works fine if I try to contact www.google.com on say port 81, but for some reason if I try to connect to an unopen port on 127.0.0.1 or my router's IP, it succesds all the time.

The method I used is : first I set the socket to non-blocking, tried connecting with connect(), not bothering to check the return value because its always -1, then using select() to check if the socket could be written to.

heres my code:
Code:

bool TcpClient::Connect(        const char* host,
                                const unsigned short port,
                                const unsigned short timeOut)
{
        // get the IP address
        struct hostent* h=gethostbyname(host);
        if (!h) return false;

        // create socket and set it to non-blocking
        sockfd=socket(PF_INET,SOCK_STREAM,0);
        fcntl(sockfd,F_SETFL,O_NONBLOCK);

        // set up address structure
        remoteAddr.sin_port=htons(port);
        memcpy(&(remoteAddr.sin_addr.s_addr),h->h_addr,sizeof(remoteAddr.sin_addr.s_addr));

        // attempt to connect
        connect(sockfd,(struct sockaddr*)&remoteAddr,sizeof(struct sockaddr));

        // set up file descriptor set
        FD_ZERO(&fds);
        FD_SET(sockfd,&fds);

        // set up timeval struct
        tv.tv_sec=timeOut;
        tv.tv_usec=0;

        // monitor the socket
        if (select(sockfd+1,NULL,&fds,NULL,&tv)<=0)
        {
                close(sockfd);
                return false;
        }

        return true;
}

Thanks for any help.

nodger 10-21-2006 03:34 PM

hmm.. i think Ive found a solution. if I just call send(sockfd,0,0,0) and I get a return value of 0, then its connected.

_john_i_ 10-21-2006 08:58 PM

A method I have used before is to create a signal handler function for SIGALRM, and before calling connect call alarm(timeout); and after the connect call alarm(0);

When the alarm goes off and your signal handler returns, connect will exit, and you just turn off the alarm with the alarm(0).

paulsm4 10-21-2006 11:14 PM

Hi -

There are several ways for a sockets client to "connect() with timeout":

Quote:

1. Timeout with "select()"
I really wouldn't recommend this one for your situation. At best, if I was using UDP "sendto()" and "recvfrom ()", I might use "select()" to verify that the socket became writeable or readable within a specific time before I used it.
Quote:

2. Sigalarm
_john_i_'s suggestion is a good one. For example:
Code:

  /* Adapted from W. Richard Stevens, "Unix Network Programming" */
  oldsigfunc = signam (SIGALRM, mynewfunc);
  if (alarm (nsec) != 0) {
    printf ("WARNING: Alarm already set!\n");
  }

  /* Try to connect */
  iretval = connect (sockfd, &sa, slen);
  if (iretval  < 0) {
    close (sockfd);
    if (errno == EINTR)
      printf ("WARNING: timeout occurred...\n");
  }

  /* Clear Alarm/reset original SIGALRM handler */
  alarm (0);
  signal (SIGALRM, oldsigfunc);

  /* ... continue or not, based on "iretval" ... */


Quote:

3. "setsockopt (SO_RCVTIMEO)"
This is the best option of all ... if your stack supports it.

My version of Stevens (the 2nd Edition, 1998) states that you CANNOT use "setsockopt(SO_RCVTIMEO)" to set a connect timeout. This is no longer true on most OS's, and it has been available on Linux since kernel 2.3.41.
<= If at all possible, I'd encourage you to consider SO_RECVTIMEO
'Hope that helps .. PSM

PS:
Here are some links:
http://publib.boulder.ibm.com/infoce...2/gtpc2m2u.htm
http://linuxreviews.org/man/socket/


All times are GMT -5. The time now is 01:57 PM.