반응형

TCP/IP 기본 함수


int TCPIPconnect(const char *addr, int port)
함수 

TCP/IP에서 서버로 접속할 client의 connect함수입니다. 이 함수는 client가 server로 접속할 때에 IP address(예, 110.45.229.135) 이든지, domain(downman.tistory.com) 방식이든 아무 주소 형태로 접속할 수 있도록 하는 함수입니다.

/*
* 주소 정보가 IP address인지 domain명인지를 판단하기 위한 함수
* IP address이면 1 그렇지 않으면 0을 return 함
*/
static int is_ipaddr(const char *addr)
{
    while(*addr) {
        if(('0' <= *addr && *addr <= '9') || *addr == '.') {
            addr++;
            continue;
        } else {
            return 0;
        }
    }
    return 1;
}

/*===================================================================================
* client socket을 생성하여 server socket으로 접속합니다.
* 파라미터: 
*       addr : 접속할 서버의 주소
*              IP address 또는 domain 형식 (ex. 127.0.0.1 또는 downman.tistory.com)
*       port : 접속할 port 번호
* return :
*       0이상 : 접속한 socket descriptor
*       -1    : 오류발생, 상세 오류는 errno 전역변수 확인
===================================================================================*/
int TCPIPconnect(const char *addr, int port)
{
    struct hostent *he;
    struct sockaddr_in server_addr;
    int  sock;

    memset(&server_addr, 0x00, sizeof(struct sockaddr_in));
    server_addr.sin_family    = AF_INET;
    server_addr.sin_port      = htons(port);

    if(is_ipaddr(addr)) {  // IP 주소로 접속할려면...
        server_addr.sin_addr.s_addr  = inet_addr(addr);
    } else { // domain명으로 접속하려면...
        if((he = gethostbyname(addr)) == NULL) {
            return -1;
        }

        memcpy(&server_addr.sin_addr.s_addr, he->h_addr, he->h_length);
    }
    
    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        return -1;
    }

    if(connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1) {
        close(sock);
        return -1;
    }
    return sock;
}

 


 

int TCPIPserver(int port)함수 

Serve socket을 생성하는 함수입니다. 내부적으로 socket(2), bind(2), listen(2)을 한 번에 처리합니다. 또한, port번호를 재 사용할 수 있도록 socket의 option을 설정합니다. 서버 프로그램이 종료후에 바로 다시 실행해야하는 경우에는 SO_REUSEADDR을 설정하지 해야 합니다. 그렇지 않으면 port가 사용중이라는 오류가 발생하여 1분 이상 socket생성을 할 수 없습니다. 이 option이 설정되었다고 해서 실행중인 서버가 있는 데, 2개를 실행할 수 있는 것은 아닙니다. 종류후 다시 실행을 바로 해야 하는 경우에만 바로 실행할 수 있도록 할 뿐입니다.

/*===================================================================================
* server socket을 생성합니다.
* 파라미터 :
*        port : 서버 소켓의 port 번호
* return :
*        0 이상 : socket()/bind()가 완료된 server socket 
*        -1     : 오류발생, 상세 오류는 errno 전역변수 확인
===================================================================================*/
int TCPIPserver(int port)
{
    int    server_fd;
    int    reuse        = 1;
    struct sockaddr_in server;

    if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        return -1;
    }

    /* 
    * 프로그램을 restart해야하는 경우에 프로그램 종료후 바로 재실행하는 경우 
    * SO_REUSEADDR을 설정하지 않으면 1분이상 port 번호가 해제되지 않아서 bind 오류가 발생함.
    */
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    
    server.sin_family      = AF_INET;
    server.sin_port        = htons(port);
    server.sin_addr.s_addr = INADDR_ANY;

    if(bind(server_fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
        return -1;
    }

    if(listen(server_fd, 50) == -1) {
        return -1;
    }
    
    return server_fd;
}

 


 

int TCPIPaccept(int server_fd, struct sockaddr_in *client) 함수 

Client의 요청을 받아드리고 새로운 socket을 생성합니다. 접속한 client의 정보(IP, port)를 얻습니다. client 파라미터를 NULL로 설정하면 client의 접속정보를 얻지 않습니다.

/*===================================================================================
* TCPIPaccept : client의 접속 요청을 받아들여 client와 연결된 새로운 socket을 생성합니다.
* 파라미터 :
*        server_fd : TCPIPserver()가 return한 server socket descriptor
*        client    : 접속한 client의 IP 및 port 정보
* return :
*        0 이상 : client와 접속한 socket descirptor 
*        -1     : 오류발생, 상세 오류는 errno 전역변수 확인
===================================================================================*/
int TCPIPaccept(int server_fd, struct sockaddr_in *client)
{
    int connected_fd;
    socklen_t addr_len = 0;

    if(client != NULL) {
        addr_len = sizeof(struct sockaddr_in);
    }
    
    if((connected_fd = accept(server_fd, (struct sockaddr *)client, &addr_len)) == -1) {
        return -1;   
    }

    return connected_fd;
}

 


 

ssize_t TCPIPsend(int sockfd, const void *buf, size_t len, int flags) 함수 

data를 전송합니다. signal발생하면 signal을 무시하고 재처리합니다.

/*===================================================================================
* TCPIPsend : 연결된 socket으로 데이터를 전송합니다.
* 파라미터 :
*        sockfd : TCPIPconnect() 또는 TCPIPaccept()가 reutrn한 socket descriptor
*        buf    : 전송할 데이터
*        len    : 전송할 데이터 byte수
*        flags  : 일반적으로 0을 설정합니다.  
*                 MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB 등을 사용할 수 있습니다.
* return :
*        0 이상 : 실제 전송된 데이터 byte수 
*        -1     : 오류발생, 상세 오류는 errno 전역변수 확인
===================================================================================*/
ssize_t TCPIPsend(int sockfd, const void *buf, size_t len, int flags)
{
    ssize_t size;

    while((size = send(sockfd, buf, len, flags)) == -1 && errno != EINTR );

    return size;
}

 


 

ssize_t TCPIPrecv(int sockfd, void *buf, size_t len, int flags) 함수 

data를 수신합니다. signal발생하면 signal을 무시하고 재처리합니다.

/*===================================================================================
* TCPIPrecv : 연결된 socket으로부터 데이터를 수신합니다.
* 파라미터 :
*        sockfd : TCPIPconnect() 또는 TCPIPaccept()가 reutrn한 socket descriptor
*        buf    : 수신후 저장할 데이터 buffer
*        len    : 수신할 데이터 byte 수
*        flags  : 일반적으로 0을 설정합니다.  
*                 MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB 등을 사용할 수 있습니다.
* return :
*        0 이상 : 실제 수신한 데이터 byte수 
*        -1     : 오류발생, 상세 오류는 errno 전역변수 확인
===================================================================================*/
ssize_t TCPIPrecv(int sockfd, void *buf, size_t len, int flags)
{
    ssize_t size;

    while((size = recv(sockfd, buf, len, flags)) == -1 && errno != EINTR );

    return size;
}

 


 

int TCPIPclose(int sockfd) 함수 

더 이상 사용하지 않을 socket을 close합니다.

/*===================================================================================
* TCPIPclose : 생성된 socket을 close합니다.
* 파라미터 :
*        sockfd : TCPIPconnect(), TCPIPaccept(), TCPIPserver() 등으로 생성한 socket descriptor
* return :
*        0      : 정상적으로 close 됨.
*        -1     : 오류 발생
===================================================================================*/
int TCPIPclose(int sockfd)
{
    return close(sockfd);
}

 


see also :  TCP/IP 통신 프로그램   Socket 통신 관련 Library  

반응형
블로그 이미지

자연&사람

행복한 개발자 programmer since 1995.

,