方案1: int connect_socket_timeout(int sockfd,char *dest_host, int port, int timeout) { struct sockaddr_in address; struct in_addr inaddr; struct hostent *host; int err, noblock=1 , connect_ok=0, begin_time=time(NULL); log_debug("connect_socket to %s:%d\n",dest_host,port); if (inet_aton(dest_host, &inaddr)) { // log_debug("inet_aton ok now gethostbyaddr %s\n",dest_host); memcpy(&address.sin_addr, &inaddr, sizeof(address.sin_addr)); } else { log_debug("inet_aton fail now gethostbyname %s \n",dest_host); host = gethostbyname(dest_host); if (!host) { /* We can't find an IP number */ log_error("error looking up host %s : %d\n",dest_host,errno); return -1; } memcpy(&address.sin_addr, host->h_addr_list[0], sizeof(address.sin_addr)); } address.sin_family = AF_INET; address.sin_port = htons(port); /* Take the first IP address associated with this hostname */ ioctl(sockfd,FIONBIO,&noblock); /** connect until timeout */ /* EINPROGRESS A nonblocking socket connection cannot be completed immediately. EALREADY The socket is nonblocking and a previous connection attempt has not been completed. EISCONN The socket is already connected. */ if (connect(sockfd, (struct sockaddr *) &address, sizeof(address)) < 0) { err = errno; if (err != EINPROGRESS) { log_error("connect = %d connecting to host %s\n", err,dest_host); } else { // log_notice("connect pending, return %d \n", err); while (1) /* is noblocking connect, check it until ok or timeout */ { connect(sockfd, (struct sockaddr *) &address, sizeof(address)); err = errno; switch (err) { case EISCONN: /* connect ok */ connect_ok = 1; break; case EALREADY: /* is connecting, need to check again */ // log_info("connect again return EALREADY check again...\n"); usleep(50000); break; // default: /* failed, retry again ? */ log_error("connect fail err=%d \n",err); // connect_ok = -1; // break; } if (connect_ok==1) { // log_info ("connect ok try time =%d \n", (time(NULL) - begin_time) ); break; } if (connect_ok==-1) { log_notice ("connect failed try time =%d \n", (time(NULL) - begin_time) ); break; } if ( (timeout>0) && ((time(NULL) - begin_time)>timeout) ) { log_notice("connect failed, timeout %d seconds\n", (time(NULL) - begin_time)); break; } } } } else /* Connect successful immediately */ { // log_info("connect immediate success to host %s\n", dest_host); connect_ok = 1; } /** end of try connect */ return ((connect_ok==1)?sockfd:-1); } |
|