int SocketConnectTimeout(char *ip, int iport, int isec)
{
struct sockaddr_in dstAddr;
int status;
int flag;
int len = 0;
int fd = -1;
int sockOpt=1;
int reUseOpt=1;
fd_set rSet;
fd_set wSet;
struct timeval tv;
if(ip == NULL || iport <= 0 || isec <= 0) {
fprintf(stderr, "invalid ip or invalid iport or invalid timeout(%s,%d,%d)\n", ip, iport, isec); fflush(stderr);
return -1;
}
dstAddr.sin_family = AF_INET;
dstAddr.sin_port = htons(iport);
dstAddr.sin_addr.s_addr = inet_addr(ip);
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket create fail\n"); fflush(stderr);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&sockOpt, sizeof(sockOpt)) < 0) {
fprintf(stderr, "setsockopt(SO_KEEPALIVE) fail. errno=%d(%s)\n", errno,strerror(errno));
close(fd);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reUseOpt, sizeof(reUseOpt)) < 0) {
fprintf(stderr, "setsockopt(SO_REUSEADDR) fail. errno=%d(%s)\n", errno,strerror(errno));
close(fd);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)&reUseOpt, sizeof(reUseOpt)) < 0) {
fprintf(stderr, "setsockopt(SO_REUSEPORT) fail. errno=%d(%s)\n", errno,strerror(errno));
close(fd);
return -1;
}
struct linger solinger = { 1, 0 };
if(setsockopt(fd, SOL_SOCKET, SO_LINGER, &solinger, sizeof(struct linger)) < 0) {
fprintf(stderr, "setsockopt (SO_LINGER) fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
if((flag = fcntl(fd, F_GETFL, 0)) < 0) {
fprintf(stderr, "fcntl get fd fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
if(fcntl(fd, F_SETFL, flag|O_NONBLOCK) < 0) {
fprintf(stderr, "fcntl nonblock fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
status = connect(fd, (struct sockaddr *)&dstAddr, sizeof(dstAddr));
if((status < 0) && (errno != EINPROGRESS)) {
fprintf(stderr, "connect fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
else if(status == 0) {
if(fcntl(fd, F_SETFL, flag) < 0) {
fprintf(stderr, "fcntl block fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
else {
return fd;
}
}
else {
FD_ZERO(&rSet);
FD_SET(fd, &rSet);
wSet = rSet;
tv.tv_sec = isec;
tv.tv_usec = 0;
if(select(fd+1, &rSet, &wSet, NULL, &tv) == 0) {
fprintf(stderr, "socket connect timeout. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
if(FD_ISSET(fd, &rSet) || FD_ISSET(fd, &wSet)) {
int error = 0;
len = sizeof(error);
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
fprintf(stderr, "getsockopt fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
if(error) {
fprintf(stderr, "connect fail getsockopt fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
}
else {
fprintf(stderr, "select error. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
if(fcntl(fd, F_SETFL, flag) < 0) {
fprintf(stderr, "fcntl block fail. errno=%d(%s)\n", errno,strerror(errno)); fflush(stderr);
close(fd);
return -1;
}
else {
return fd;
}
}
}