출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Network_Programing/Documents/Sockettimeout
connect timeout
connect timeout에 대해서 다룰 것이다. 이 내용은 완성되면 아래의 문서에 추가될 것이다.
아래의 내용에는 connect 타입아웃에 대해서는 언급되지 않고 있다. 다음과 같은 방식으로 connect 타임아웃을 구현할 것이다.
- fcntl(2) 함수를 이용해서 듣기소켓을 비동기 소켓으로 만든다.
- connect(2)를 호출하면 바로 리턴될 것이다.
- select(2)를 이용해서 timeout을 체크하도록 한다.
- timeout 체크가 끝난 뒤에는 소켓을 원래의 blocking 상태로 되돌린다.
#include <sys/stat.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> int ConnectWait(int sockfd, struct sockaddr *saddr, int addrsize, int sec) { int newSockStat; int orgSockStat; int res, n; fd_set rset, wset; struct timeval tval; int error = 0; int esize; if ( (newSockStat = fcntl(sockfd, F_GETFL, NULL)) < 0 ) { perror("F_GETFL error"); return -1; } orgSockStat = newSockStat; newSockStat |= O_NONBLOCK; // Non blocking 상태로 만든다. if(fcntl(sockfd, F_SETFL, newSockStat) < 0) { perror("F_SETLF error"); return -1; } // 연결을 기다린다. // Non blocking 상태이므로 바로 리턴한다. if((res = connect(sockfd, saddr, addrsize)) < 0) { if (errno != EINPROGRESS) return -1; } printf("RES : %d\n", res); // 즉시 연결이 성공했을 경우 소켓을 원래 상태로 되돌리고 리턴한다. if (res == 0) { printf("Connect Success\n"); fcntl(sockfd, F_SETFL, orgSockStat); return 1; } FD_ZERO(&rset); FD_SET(sockfd, &rset); wset = rset; tval.tv_sec = sec; tval.tv_usec = 0; if ( (n = select(sockfd+1, &rset, &wset, NULL, NULL)) == 0) { // timeout errno = ETIMEDOUT; return -1; } // 읽거나 쓴 데이터가 있는지 검사한다. if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset) ) { printf("Read data\n"); esize = sizeof(int); if ((n = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&esize)) < 0) return -1; } else { perror("Socket Not Set"); return -1; } fcntl(sockfd, F_SETFL, orgSockStat); if(error) { errno = error; perror("Socket"); return -1; } return 1; } int main(int argc, char **argv) { struct sockaddr_in serveraddr; int sockfd; int len; if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror("error"); return 1; } serveraddr.sin_family = AF_INET; serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serveraddr.sin_port = htons(atoi(argv[1])); len = sizeof(serveraddr); if (ConnectWait(sockfd, (struct sockaddr *)&serveraddr, len, 5) < 0) { perror("error"); } else { printf("Connect Success\n"); } while(1) { sleep(1); } close(sockfd); }
'UNIX_LINUX_C_C++' 카테고리의 다른 글
TCP/IP 네트웍 어플리케이션 문제발생과 해결 (0) | 2011.10.16 |
---|---|
Pcap 을 이용한 패킷캡쳐응용 (0) | 2011.10.16 |
[FreeTDS] The stream ended unexpectedly 에러 발생 (0) | 2011.10.16 |
[펌] TCP 자세히 보기 (0) | 2011.10.16 |
bind error : Address already in use (0) | 2011.10.16 |