'programming'에 해당되는 글 387건

  1. 2016.11.08 SocketConnectTimeout

반응형



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;

        }

    }

}

반응형
Posted by 공간사랑
,