[Nework][TCP/IP] Hand made Ping

Ping server & Ping clinet

이전에 공부한 socket, bind, listen, accept, connect 등의 함수를 이용해 간단한 echo 서버를 만들었다.

기본적인 골격은 아래와 같다.

socket_flow

서버에서 연결 준비를 거친 뒤 클라이언트에서 연결한다.
이후 클라이언트에서 write 함수를 통해 입력 받은 값을 서버에게 전달한다.
서버는 전달 받은 데이터를 read 함수를 통해 한번 읽어 저장한 뒤 write 함수로 클라이언트에게 전달한다.
서버로부터 데이터를 전달 받은 클라이언트는 read 함수를 통해 정보를 저장한 뒤 다시 데이터를 입력 받을 준비를 한다.

지속적으로 데이터를 읽고 쓰는 방식은 read 와 write 함수 부분에 while 문을 넣는 아주 간단한 방식을 사용했다.


Server Side Code

단계 (해당 함수 혹은 구조체 명)

소켓을 연다 (socket)
    > 서버에 주소를 할당한다(sturct sockaddr_in)
       > 서버를 연다 (bind)
           > 연결을 기다린다.(listen)
               > 연결이 오면 허가한다.(accept)
                   > 데이터를 주고 받는다.(read/write)
> 연결을 종료한다. (close)

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

enum{CMD, PORT};

int main(int argc, char * argv[])
{
    int sock, sock_clinet;
    int sock_client_len;
    struct sockaddr_in sock_addr, sock_clinet_addr;
    char buf[1024];

    if(argc != 2){
        printf("Usage %s <PORT>\n",argv[CMD]);
        exit(1);
    }

// 소켓을 {{
    sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket ");
        exit(1);
    }
// }} 여는 부분

// 서버의 주소를{{ 
    memset(&sock_addr,0x00,sizeof(sock_addr));
    sock_addr.sin_family = AF_INET;
    sock_addr.sin_addr.s_addr = htons(INADDR_ANY);    //INADDR_ANY는 실행 중인 컴퓨터에 IP 주소를 의미한다.
    sock_addr.sin_port=htons(atoi(argv[PORT]));
// }} 설정하는 부분

// 설정된 주소로 {{
    if(bind(sock,(struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0){
        perror("bind ");
        exit(1);
    }
// }} 서버를 여는 부분

// 연결을 {{
    if(listen(sock,5) < 0){
        perror("listen ");
        exit(1);
    }
// }} 기다리는 부분

// 클라이언트의 연결을 {{
    sock_client_len = sizeof(sock_clinet_addr);
    sock_clinet = accept(sock,(struct sockaddr *)&sock_clinet_addr, &sock_client_len);
    if(sock_clinet < 0){
        perror("accept ");
        exit(1);
    }
// 받는 부분

// 데이터를 {{
    while(1){
        if(read(sock_clinet,buf,sizeof(buf)) < 1){
            perror("read ");
            exit(1);
        }

        printf("====Ping data====\n%s\n====================\n", buf);

        if(write(sock_clinet,buf,sizeof(buf))<0){
            perror("write ");
            exit(1);
        }
    }
// }} 주고 받는 부분

    close(sock_clinet);
    close(sock);
    return 0;
}

Client Side Code

소켓을 연다 (socket)
    > 서버 주소를 삽입한다(sturct sockaddr_in)
       > 서버에게 요청한다. (connect)
           > 데이터를 주고 받는다.(read/write)
> 연결을 종료한다. (close)

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

enum{CMD, IP, PORT};

int main(int argc, char * argv[])
{
    int sock;
    struct sockaddr_in sock_addr;
    char buf[1024];

    if(argc != 3){
        printf("Useage: %s <IP> <PORT>\n", argv[CMD]);
        exit(1);
    }

// 소켓을 {{
    sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket ");
        exit(1);
    }
// }} 여는 부분

// 주소를 {{
    memset(&sock_addr,0x00,sizeof(sock_addr));
    sock_addr.sin_family = AF_INET;
    sock_addr.sin_addr.s_addr = inet_addr(argv[IP]);
    sock_addr.sin_port=htons(atoi(argv[PORT]));
// }} 설정하는 부분

// 설정된 주소로 {{
    if(connect(sock,(struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0){
        perror("connect ");
        exit(1);
    }
// }} 연결하는 부분

// 데이터를 {{
    while(1){
        printf("Input string :");
        scanf("%s",buf);

        if(write(sock,buf,sizeof(buf))<0){
            perror("write ");
            exit(1);
        }

        if(read(sock,buf,sizeof(buf))<0){
            perror("read ");
            exit(1);
        }
        printf("====Pong data====\n%s\n====================\n", buf);
    }
// }} 주고 받는 부분

    close(sock);
    return 0;
}

 

글의 문제가 있다면 댓글을 달아 주세요.

This site uses Akismet to reduce spam. Learn how your comment data is processed.