Echo Client / Echo Server

민픽minpic·2023년 5월 20일
0

[TIL] Today I Learned

목록 보기
20/25

Echo 서버와 클라이언트 만들기(Stream Sockets)

echo 서버와 클라이언트를 만들어야 해서, 우선적으로 새로운 폴더를 만들었다.

echo 디렉토리 안에, client와 server 디렉토리를 만들어주었고, 각각 Makefile 을 만들어서 make 명령어로 실행파일을 만들 수 있게 했다.

위에 tree를 보면, client 디렉토리 안에 연두색 echoclient 와 server 디렉토리 안에 연두색 echoserver는 실행 파일이다.

두 개의 터미널을 열어서 먼저 echoserver을 실행시키고, echoclient 를 실행시켜 echo 가 잘되는지 확인했다.

그리고 직접 디버그모드를 통해 클라이언트와 서버 중에 어떠한 코드가 먼저 실행되는지 확인하면서 공부했다.

서버 실행 방법(in terminal)
$ 실행파일 포트번호 

$ minpic/webproxy-lab/echo/server$ ./echoserver 52184
client 실행 방법 (in terminal)
$ 실행파일 퍼블릭IP 포트번호

$ minpic/webproxy-lab/echo/client$ ./echoclient 52.199.9.231 52184

echo 서버와 클라이언트 코드는 컴퓨터시스템 책의 나와있는 코드로 작성하였다.

주석을 통해서 순서를 적어놓았다.

echoserver.c

#include "../csapp.h"


void echo (int connfd);

int main(int argc, char **argv){
    int listenfd, connfd;
    socklen_t clientlen;
    struct sockaddr_storage clientaddr;
    char client_hostname[MAXLINE], client_port[MAXLINE];

    if(argc != 2){
        fprintf(stderr, "usage: %s <port>\n", argv[0]); // 서버 실행시 포트 번호 지정
        exit(0);
    }

    listenfd = Open_listenfd(argv[1]); // 1. socket(), bind(), listen() 서버 열기

    while(1) {
        clientlen = sizeof(struct sockaddr_storage);
        connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); // 3. client accept! 
        Getnameinfo((SA *) &clientaddr, clientlen, client_hostname, MAXLINE,
                client_port, MAXLINE, 0); // 4. client 정보 가져오기
        printf("Connected to (%s, %s)\n", client_hostname, client_port);

        echo(connfd); // 8. client 에서 받은 값을 다시 client 보내주기 

        Close(connfd);
    }
    exit(0);
}
echoclient.c

#include "../csapp.h"

int main(int argc, char **argv){
    int clientfd;
    char *host, *port, buf[MAXLINE];
    rio_t rio;

    if(argc != 3){
        fprintf(stderr, "usage: %s <host> <port>\n", argv[0]);
        exit(0);
    }

    host = argv[1];
    port = argv[2];

    // ubuntu: 52184
    clientfd = Open_clientfd(host, port); // 2. socket(), connect() 서버 연결

    Rio_readinitb(&rio, clientfd); // 5. RIO 패키지를 사용하여 clientfd로부터 읽기 위한 버퍼를 초기화.
    while (Fgets(buf, MAXLINE, stdin) != NULL){ // 6. 사용자로 부터 입력 값 받고
        Rio_writen(clientfd, buf, strlen(buf)); // 7. 입력 값을 서버 전달
        Rio_readlineb(&rio, buf, MAXLINE);      // 9. 서버에서 보내준 값 읽기
        Fputs(buf, stdout);                     // 10. 읽은 값을 터미널에 보여주기

    }
    Close(clientfd);
    exit(0);
}
profile
사진찍는 개발자 / 한 가지 개념이라도 깊이있게

0개의 댓글