검색결과 리스트
글
connect() 함수에 타이머 걸기가 어렵게 느껴지는 이유는
connect() 함수가 블럭킹되는 함수이기 때문입니다.
이를 해결하기 위해서...
connect() 함수로 연결을 기다리기 전에
소켓을 non-block 모드로 설정한후에
connect() 호출합니다. 그러면 connect()가 즉시 리턴하거든요, 연결이 되든 안되든...
그후 select()를 호출하면 됩니다.
non-block 소켓이 연결되거나, 타임아웃이 되면 select() 함수가 리턴합니다.
select() 함수의 리턴값을 보고, 연결되었는지 타임아웃인지를 확인할수 있습니다.
그니깐 순서가..
1. 소켓을 non-block 으로 설정
2. connect() 호출--- 즉시 리턴
3. select()로 타임아웃을 기다림
4. 소켓의 non-block 을 해제
머 이런순으로 되겠죠
책보면 다나오는 것이지만... 혹시나 고수님들의 딴지를 기대하며
제가 작성한 소스를 올려봅니다.
님이 궁금해하시는 소스는 connect_nonb() 부분일겁니다.
int tcp_connect_timeo(const char *hostname, const char *service,int nsec) { struct addrinfo hints, *res, *ressave; int sock,n; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if( (n=getaddrinfo(hostname,service,&hints,&res)) != 0) return -1; ressave = res; do { struct sockaddr_in *ts; sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if(sock < 0) continue; ts = (struct sockaddr_in *) res->ai_addr; if(connect_nonb(sock, (struct sockaddr *)res->ai_addr, res->ai_addrlen,nsec) == 0) break; close(sock); }while( (res=res->ai_next) !=NULL); if( res == NULL) return -1; freeaddrinfo(ressave); return sock; } int connect_nonb(int sockfd, const struct sockaddr *saptr, int 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); }
'Network > socket(c&c++)' 카테고리의 다른 글
TCP/IP 통신 함수 사용 순서 (0) | 2012.10.22 |
---|---|
클라이언트 소켓에서 Connection Time out (0) | 2012.10.19 |
The C10K problem (0) | 2012.10.19 |
TCP 기반의 소켓 통신 101 (0) | 2012.10.19 |
non-block / block 혼합 구현 서버 소스 (0) | 2012.10.19 |
RECENT COMMENT