'programming/C_C++'에 해당되는 글 279건

  1. 2013.01.08 socket connect timeout host service

반응형

 

 


//------------------------------------------------------------------------------


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netdb.h>
#include <fcntl.h>

//------------------------------------------------------------------------------

int SocketConnect(char *sHostIp, char *sServicePort, int nTimeout)
{
    int  nRet = -1;
    int  nRealPort = -1;
    int  nSockFd = -1;

    struct sockaddr_in name;

    struct hostent *hp;
    struct servent *sp;

    nSockFd = socket (AF_INET, SOCK_STREAM, 0);
    if ( nSockFd < 0 )  {
        fprintf(stderr, "socket open error : %d[%s]\n", errno, strerror(errno) );  fflush(stderr);
        return -1;
    }

    if ( !isdigit(sServicePort[0]) ) {  /* 숫자값이 아닐경우 즉 서비스명으로 되어 있을 경우 만약 서비스명의 맨앞이 숫자로 되어있는경우 구분이 안되는 문제가 생기게됨.*/

        sp = getservbyname ( sServicePort, "tcp");
        if ( sp == NULL )  {
            fprintf(stderr, "getservbyname error : [%s]\n", sServicePort);
            return -1;
        }
        else {
            nRealPort = sp->s_port;
        }

    }
    else {  /* 숫자값으로 되어 있을 경우 즉 PORT번호로 되어 있을 경우 */

        nRealPort = atoi(sServicePort);

    }

    if( nRealPort <= 0 ) {

        fprintf(stderr, "Invalid RealPort error : [%d]\n", nRealPort);
        return -1;

    }

    if ( !isdigit(sHostIp[0]) ) {  /* 숫자가 아닌 HOST명으로 되어 있을 경우 호스트명의 맨앞이 숫자로되어 있을 경우 구분이 안되는 문제가 생길수 있음 */

        hp = gethostbyname (sHostIp);

        if ( hp == NULL )  {
            fprintf(stderr, "gethostbyname error :[%s]\n", sHostIp);
            return -1;
        }

        memcpy ( (char *)&name.sin_addr, hp->h_addr_list[0], hp->h_length );
        name.sin_family = hp->h_addrtype;

    }
    else {  /* 숫자값 즉 IP로 되어 있을 경우 */

        name.sin_addr.s_addr = inet_addr (sHostIp);
        name.sin_family = AF_INET;
    }

    name.sin_port = ntohs(nRealPort);

    nRet = ConnectTimeout( nSockFd, (struct sockaddr *)&name, sizeof(name), nTimeout );
    if( nRet < 0 ) {
        fprintf(stderr, "ConnectTimeout error : nRet[%d][%d][%s]\n", nRet, errno, strerror(errno));
        return -1;
    }

    return nSockFd;

}

//------------------------------------------------------------------------------

int ConnectTimeout(int sfd, struct sockaddr *serv_addr, socklen_t addrlen, int timeout)
{
    int nRet, slen, flags;
    struct timeval tv;
    struct sockaddr_in addr;
    fd_set rdf, wrf;

    flags = fcntl(sfd, F_GETFL, 0);
    fcntl(sfd, F_SETFL, flags | O_NONBLOCK);

    nRet = connect(sfd, serv_addr, addrlen);

    if (nRet  >= 0) {  /* connect completed immediately */

        return nRet ;

    }
    else {

        if (errno != EINPROGRESS) {  /* 에러이면서 connect 처리중인 상태가 아닐경우 */

            close(sfd);
            return (-1);

        }

    }

    FD_ZERO(&rdf);
    FD_ZERO(&wrf);

    FD_SET(sfd, &rdf);
    FD_SET(sfd, &wrf);

    bzero(&tv, sizeof(tv));
    tv.tv_sec = timeout;
    tv.tv_usec = 0;

    if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0) {  /* timeout */

        close(sfd);
        errno = ETIMEDOUT;
        return (-1);

    }

    if ( FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf) ) {

        slen = sizeof(addr);

        if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1) {

            close(sfd);
            return (-1);

        }

        flags = fcntl(sfd, F_GETFL, 0);
        fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);

        return 0;

    }
    else {

        close(sfd);
        return (-1);

    }

}

//------------------------------------------------------------------------------

int main(int argc, char *argv[])
{

    int nSockFd = -1;

    char sHostIp[30];
    char sServicePort[30];

    int nTimeout = 3;

    if( argc != 3 ) {
        fprintf(stdout, "USAGE : %s [HOST | IP] [SERVICE | PORT]  \n", argv[0]);
        exit(0);
    }

    memset(sHostIp, 0x00, sizeof(sHostIp));
    sprintf(sHostIp, "%s", argv[1]);

    memset(sServicePort, 0x00, sizeof(sServicePort));
    sprintf(sServicePort, "%s", argv[2]);

    nSockFd = SocketConnect(sHostIp, sServicePort, nTimeout);
    if( nSockFd < 0 ) {
        fprintf(stderr, "SocketConnect fail \n");
        return 0;
    }

    fprintf(stdout, "SocketConnect Ok \n");


    /** socket send / socket recv **/

    close(nSockFd);
}


//------------------------------------------------------------------------------

 

 

 

 

 

 

반응형
Posted by 공간사랑
,