//------------------------------------------------------------------------------
#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);
}
//------------------------------------------------------------------------------









