'programming/C_C++'에 해당되는 글 279건

  1. 2008.05.21 socket connect timeout

반응형

socket connect timeout

http://newtype.pe.kr/345

connection 할때 timeout 처리

nonblocking socket을 이용한 Rechard stevens의 소스

<<Rechard stevens 소스>>

int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)
{
 int    flags, n, error;
 socklen_t  len;
 fd_set   rset, wset;
 struct timeval tval;

 flags = Fcntl(sockfd, F_GETFL, 0);
 Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

 error = 0;
 if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0)
  if (errno != EINPROGRESS)
   return(-1);

 /* Do whatever we want while the connect is taking place. */

 if (n == 0)
  goto done; /* connect completed immediately */

 FD_ZERO(&rset);
 FD_SET(sockfd, &rset);
 wset = rset;
 tval.tv_sec = nsec;
 tval.tv_usec = 0;

 if ( (n = Select(sockfd+1, &rset, &wset, NULL,
      nsec ? &tval : NULL)) == 0) {
  close(sockfd);  /* timeout */
  errno = ETIMEDOUT;
  return(-1);
 }

 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
  len = sizeof(error);
  if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
   return(-1);   /* Solaris pending error */
 } else
  err_quit("select error: sockfd not set");

done:
 Fcntl(sockfd, F_SETFL, flags); /* restore file status flags */

 if (error) {
  close(sockfd);  /* just in case */
  errno = error;
  return(-1);
 }
 return(0);
}

<<Rechard stevens 소스>>


예전에 포스팅 한 http socket client 에 적용하면서 windows 버전으로도 만들어 봤습니다.


int CHttpSocket::connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, struct timeval tval)
{
    int               flags, n, error;
    socklen_t         len;
    fd_set            rset, wset;

#ifdef WIN32
    int nonblocking =1;
    ioctlsocket(sockfd, FIONBIO, (unsigned long*) &nonblocking);

#else

    flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

#endif

    error = 0;
    if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0)
    {

#ifdef WIN32

        errno = WSAGetLastError();

#endif

        if (errno != EINPROGRESS && errno!= EWOULDBLOCK)
        {
            return(-1);
        }
    }

    /* Do whatever we want while the connect is taking place. */

    if (n == 0)
        goto done;    /* connect completed immediately */

    FD_ZERO(&rset);
    FD_SET(sockfd, &rset);
    wset = rset;

    if ( (n = select(sockfd+1, &rset, &wset, NULL,((tval.tv_sec>0) || (tval.tv_usec>0))? &tval : NULL)) == 0)
    {
        close(sockfd);        /* timeout */
        errno = ETIMEDOUT;
        return(-1);
    }

    if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset))
    {

#ifndef WIN32

        len = sizeof(error);
        if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
            return(-1);            /* Solaris pending error */

#endif

    } else
        return(-1); //err_quit("select error: sockfd not set");

done:

#ifdef WIN32

    nonblocking =0;
    ioctlsocket(sockfd, FIONBIO, (unsigned long*) &nonblocking);

#else

    fcntl(sockfd, F_SETFL, flags);    /* restore file status flags */

#endif

    if (error) {
        close(sockfd);        /* just in case */
        errno = error;
        return(-1);
    }
    return(0);
}


반응형
Posted by 공간사랑
,