๐ŸŒ CS:APP | Echo ์„œ๋ฒ„ ๊ตฌ์ถ• ์ ˆ์ฐจ

์ด์ˆœ๊ฐ„ยท2025๋…„ 5์›” 2์ผ

CS:APP

๋ชฉ๋ก ๋ณด๊ธฐ
20/23

๐Ÿ“ 1. ํด๋” ์ค€๋น„

cd ~/workspace/KRAFTON-JUNGLE-W8-Web-Server/webproxy-lab
mkdir echo
cd echo

webproxy-lab/echo/ ํด๋” ์•ˆ์—์„œ ์—์ฝ” ์„œ๋ฒ„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ

ํด๋”๋ช…์ด๋‚˜ ๊ฒฝ๋กœ๋Š” ๊ฐœ์ธ๋งˆ๋‹ค ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ.
์ค‘์š”ํ•œ๊ฑด echo๋ผ๋Š” ํด๋”๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“œ๋Š”๊ฒŒ ๊น”๋”ํ•˜๋‹ค๋Š” ๊ฒƒ๊ณผ
csapp.c๋‚˜ csapp.h๋ฅผ ๋ณต์‚ฌํ•ด์™€์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ


๐Ÿ“„ 2. ํŒŒ์ผ ์ƒ์„ฑ

touch echoserveri.c echoclient.c echo.c

ํ•„์š”ํ•œ 3๊ฐœ C ํŒŒ์ผ์„ ๋งŒ๋“ ๋‹ค:

  • echoserveri.c: ์„œ๋ฒ„
  • echoclient.c: ํด๋ผ์ด์–ธํŠธ
  • echo.c: ๋ฉ”์‹œ์ง€ ๋˜๋Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜

๐Ÿ“ฆ 3. CS:APP I/O ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ณต์‚ฌ

cp ../csapp.c ../csapp.h .

rio_t, Rio_readlineb() ๋“ฑ์˜ robust I/O ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”


โœ๏ธ 4. ์ฝ”๋“œ ์ž‘์„ฑ

๐Ÿง  echo.c

#include "csapp.h" // robust I/O ํ•จ์ˆ˜์™€ ๊ด€๋ จ ๊ตฌ์กฐ์ฒด๋ฅผ ํฌํ•จํ•œ ํ—ค๋” ํŒŒ์ผ ํฌํ•จ

// ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ(connfd)๋ฅผ ์ธ์ž๋กœ ๋ฐ›์Œ
void echo(int connfd) {
    size_t n;               // ์ฝ์€ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ์ €์žฅํ•  ๋ณ€์ˆ˜
    char buf[MAXLINE];      // ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์˜ฌ ๋ฒ„ํผ (ํ•œ ์ค„ ์ตœ๋Œ€ MAXLINE ํฌ๊ธฐ)
    rio_t rio;              // robust I/O์šฉ ๋ฒ„ํผ ๊ตฌ์กฐ์ฒด

    // connfd(ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ rio ๊ตฌ์กฐ์ฒด ์ดˆ๊ธฐํ™”
    Rio_readinitb(&rio, connfd);

    // ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ํ•œ ์ค„์”ฉ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์† ์ฝ์–ด๋“ค์ด๋Š” ๋ฐ˜๋ณต๋ฌธ
    while ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
        // ์ฝ์€ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ์„œ๋ฒ„ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅ
        printf("server received %zu bytes\n", n);

        // ์ฝ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‹ค์‹œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋Œ๋ ค๋ณด๋ƒ„ (Echo!)
        Rio_writen(connfd, buf, n);
    }
}

๐Ÿง  echoserveri.c

๐Ÿ“Œ echoserver ๋’ค์— ๋ถ™๋Š” i๋Š” ๋ฌด์Šจ ๋œป?

i๋Š” iterative์˜ ์•ฝ์ž๋กœ,
ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ํด๋ผ์ด์–ธํŠธ๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ˜๋ณตํ˜• ์„œ๋ฒ„(iterative server)์ž„์„ ์˜๋ฏธ

#include "csapp.h" // robust I/O ํ•จ์ˆ˜์™€ ๋„คํŠธ์›Œํฌ ํ•จ์ˆ˜ ๋ž˜ํผ๊ฐ€ ํฌํ•จ๋œ ํ—ค๋” ํŒŒ์ผ

int main(int argc, char **argv) {
    int listenfd, connfd;                       // ์„œ๋ฒ„ ๋ฆฌ์Šจ์šฉ ์†Œ์ผ“๊ณผ ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ์šฉ ์†Œ์ผ“
    socklen_t clientlen;                        // ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ ๊ตฌ์กฐ์ฒด์˜ ํฌ๊ธฐ
    struct sockaddr_storage clientaddr;         // ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ ์ •๋ณด๋ฅผ ์ €์žฅํ•  ๊ตฌ์กฐ์ฒด
    char client_hostname[MAXLINE];              // ํด๋ผ์ด์–ธํŠธ์˜ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„ ๋ฌธ์ž์—ด
    char client_port[MAXLINE];                  // ํด๋ผ์ด์–ธํŠธ์˜ ํฌํŠธ ๋ฒˆํ˜ธ ๋ฌธ์ž์—ด

    // ๋ช…๋ น์ค„ ์ธ์ž๊ฐ€ 2๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ฉด ์‚ฌ์šฉ๋ฒ• ์ถœ๋ ฅ ํ›„ ์ข…๋ฃŒ
    if (argc != 2) {
        fprintf(stderr, "usage: %s <port>\n", argv[0]); // ์‹คํ–‰ ๋ฐฉ๋ฒ• ์•ˆ๋‚ด
        exit(0);
    }

    // ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ์„œ๋ฒ„ ๋ฆฌ์Šจ ์†Œ์ผ“ ์—ด๊ธฐ
    listenfd = Open_listenfd(argv[1]);

    while (1) { // ๋ฐ˜๋ณตํ˜• ์„œ๋ฒ„: ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ ์˜ฌ ๋•Œ๋งˆ๋‹ค ๋ฐ˜๋ณต
        clientlen = sizeof(struct sockaddr_storage); // ์ฃผ์†Œ ๊ตฌ์กฐ์ฒด ํฌ๊ธฐ ์ดˆ๊ธฐํ™”

        // ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ์š”์ฒญ ์ˆ˜๋ฝ โ†’ ์ƒˆ๋กœ์šด ์†Œ์ผ“ connfd ์ƒ์„ฑ
        connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);

        // ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๋ฅผ ์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ํ˜ธ์ŠคํŠธ/ํฌํŠธ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
        Getnameinfo((SA *)&clientaddr, clientlen,
                    client_hostname, MAXLINE,
                    client_port, MAXLINE, 0);

        // ์ ‘์†ํ•œ ํด๋ผ์ด์–ธํŠธ์˜ ์ •๋ณด ์ถœ๋ ฅ
        printf("connected to (%s, %s)\n", client_hostname, client_port);

        // ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์„ echo ์ฒ˜๋ฆฌ ํ•จ์ˆ˜๋กœ ๋„˜๊ฒจ ์‘๋‹ต ์ฒ˜๋ฆฌ
        echo(connfd);

        // ํด๋ผ์ด์–ธํŠธ์™€์˜ ์—ฐ๊ฒฐ ์ข…๋ฃŒ
        Close(connfd);
    }
}

๐Ÿง  echoclient.c (ํด๋ผ์ด์–ธํŠธ)

#include "csapp.h" // robust I/O ํ•จ์ˆ˜๋“ค๊ณผ ๋„คํŠธ์›Œํฌ ๋ž˜ํผ ํ•จ์ˆ˜๋“ค์ด ์ •์˜๋œ ํ—ค๋”

int main(int argc, char **argv) {
    int clientfd;               // ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ๋œ ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ
    char *host, *port;          // ๋ช…๋ น์ค„ ์ธ์ž๋กœ ๋ฐ›์€ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„๊ณผ ํฌํŠธ ๋ฒˆํ˜ธ
    char buf[MAXLINE];          // ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•  ๋ฒ„ํผ
    rio_t rio;                  // robust I/O์šฉ ์ž…๋ ฅ ๋ฒ„ํผ ๊ตฌ์กฐ์ฒด

    // ์ธ์ž ๊ฐœ์ˆ˜ ์ฒดํฌ: ์‹คํ–‰ ํŒŒ์ผ๋ช… + host + port โ†’ ์ด 3๊ฐœ์—ฌ์•ผ ํ•จ
    if (argc != 3) {
        fprintf(stderr, "usage: %s <host> <port>\n", argv[0]); // ์‚ฌ์šฉ๋ฒ• ์•ˆ๋‚ด
        exit(0);
    }

    // ๋ช…๋ น์ค„ ์ธ์ž์—์„œ ํ˜ธ์ŠคํŠธ์™€ ํฌํŠธ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ด
    host = argv[1];
    port = argv[2];

    // ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•˜๋Š” ์†Œ์ผ“์„ ์ƒ์„ฑํ•˜๊ณ , ์—ฐ๊ฒฐ ์‹œ๋„
    clientfd = Open_clientfd(host, port);

    // robust I/O๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด rio ๊ตฌ์กฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”
    Rio_readinitb(&rio, clientfd);

    // ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ํ•œ ์ค„์”ฉ ์ž…๋ ฅ์„ ๋ฐ›๊ณ  ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋Š” ๋ฐ˜๋ณต ๋ฃจํ”„
    while (Fgets(buf, MAXLINE, stdin) != NULL) {
        // ์ž…๋ ฅํ•œ ๋‚ด์šฉ์„ ์„œ๋ฒ„๋กœ ์ „์†ก
        Rio_writen(clientfd, buf, strlen(buf));

        // ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‘๋‹ต์„ ์ค„ ๋‹จ์œ„๋กœ ์ˆ˜์‹ 
        Rio_readlineb(&rio, buf, MAXLINE);

        // ๋ฐ›์€ ์‘๋‹ต์„ ํ™”๋ฉด์— ์ถœ๋ ฅ
        Fputs(buf, stdout);
    }

    // ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ ์ข…๋ฃŒ
    Close(clientfd);
    return 0;
}

๐Ÿ›  5. Makefile ์ž‘์„ฑ

echo ์„œ๋ฒ„๋ฅผ ์œ„ํ•œ Makefile์€ ์•„๋ž˜ ๊ฒฝ๋กœ์— ์ž‘์„ฑํ•ด์•ผํ•จ:

~/workspace/KRAFTON-JUNGLE-W8-Web-Server/webproxy-lab/echo/

๐Ÿ“ ์ „์ฒด ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ ์˜ˆ์‹œ

KRAFTON-JUNGLE-W8-Web-Server/
โ””โ”€โ”€ webproxy-lab/
    โ””โ”€โ”€ echo/
        โ”œโ”€โ”€ echo.c
        โ”œโ”€โ”€ echoserveri.c
        โ”œโ”€โ”€ echoclient.c
        โ”œโ”€โ”€ csapp.c
        โ”œโ”€โ”€ csapp.h
        โ””โ”€โ”€ Makefile    โœ… โ† ์—ฌ๊ธฐ์— Makefile๋งŒ๋“œ์„ธ

๐Ÿ“Œ ์ž‘์„ฑ ๋ฐฉ๋ฒ• (๋‹ค์‹œ ํ•œ๋ฒˆ ์ •๋ฆฌ)

cd ~/workspace/KRAFTON-JUNGLE-W8-Web-Server/webproxy-lab/echo
touch Makefile
nano Makefile   # ๋˜๋Š” vim, code, etc.

๊ทธ๋ฆฌ๊ณ  ๊ทธ ์•ˆ์— ๋‹ค์Œ ๋‚ด์šฉ์„ ๋ถ™์—ฌ ๋„ฃ์œผ๋ฉด ๋จ:

CC = gcc                 # ์‚ฌ์šฉํ•  ์ปดํŒŒ์ผ๋Ÿฌ๋Š” gcc
CFLAGS = -Wall -O2       # ์ปดํŒŒ์ผ ์‹œ ๋ชจ๋“  ๊ฒฝ๊ณ  ์ถœ๋ ฅ(-Wall) + ์ตœ์ ํ™”(-O2) ์˜ต์…˜ ์‚ฌ์šฉ
OBJS = csapp.o echo.o    # ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด ํŒŒ์ผ ๋ชฉ๋ก (์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋ชจ๋‘ ์‚ฌ์šฉํ•จ)

all: echoserveri echoclient  # make๋งŒ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ๊ธฐ๋ณธ์œผ๋กœ ๋นŒ๋“œํ•  ๋Œ€์ƒ

echoserveri: echoserveri.o $(OBJS)   # echoserveri๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํŒŒ์ผ๋“ค
	$(CC) $(CFLAGS) -o $@ $^ -pthread  # gcc -Wall -O2 -o echoserveri echoserveri.o csapp.o echo.o -pthread

echoclient: echoclient.o $(OBJS)     # echoclient๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํŒŒ์ผ๋“ค
	$(CC) $(CFLAGS) -o $@ $^ -pthread  # gcc -Wall -O2 -o echoclient echoclient.o csapp.o echo.o -pthread

clean:                 # make clean ์ž…๋ ฅ ์‹œ ์‹คํ–‰๋จ (๋นŒ๋“œ๋œ ํŒŒ์ผ๋“ค์„ ์‚ญ์ œ)
	rm -f *.o echoserveri echoclient  # ๊ฐ์ฒด ํŒŒ์ผ๊ณผ ์‹คํ–‰ํŒŒ์ผ๋“ค์„ ๋ชจ๋‘ ์‚ญ์ œ

โœ… ์š”์•ฝ

ํ•ญ๋ชฉ๋‚ด์šฉ
Makefile ์œ„์น˜webproxy-lab/echo/ ํด๋” ์•ˆ
์šฉ๋„echo ์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ์ž๋™ ์ปดํŒŒ์ผ
์ฃผ์˜๋ฐ˜๋“œ์‹œ ์†Œ์ŠคํŒŒ์ผ๋“ค๊ณผ ๊ฐ™์€ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ์–ด์•ผ ํ•จ

-pthread๋Š” csapp์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์“ฐ๋ ˆ๋“œ ๊ด€๋ จ ํ•จ์ˆ˜ ๋•Œ๋ฌธ์— ๋ฐ˜๋“œ์‹œ ํ•„์š”


๐Ÿ”จ 6. ์ปดํŒŒ์ผ

make

์‹คํ–‰ ํŒŒ์ผ ๋‘ ๊ฐœ๊ฐ€ ์ƒ๊น€:

  • echoserveri (์„œ๋ฒ„)
  • echoclient (ํด๋ผ์ด์–ธํŠธ)

๐Ÿš€ 7. ์‹คํ–‰ ํ…Œ์ŠคํŠธ

๐Ÿ–ฅ๏ธ ํ„ฐ๋ฏธ๋„ ๋ถ„ํ• 

๐Ÿ–ฅ๏ธ ํ„ฐ๋ฏธ๋„ 1 (์„œ๋ฒ„ ์‹คํ–‰)

./echoserveri 8000

๐Ÿ’ป ํ„ฐ๋ฏธ๋„ 2 (ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰)

./echoclient localhost 8000

์ž…๋ ฅํ•œ ๋ฌธ์žฅ์ด ๊ทธ๋Œ€๋กœ ๋Œ์•„์˜ค๋ฉด ์„ฑ๊ณต

์˜ˆ:

hello
hello
๊ฐ€๋‚˜๋‹ค๋ผ
๊ฐ€๋‚˜๋‹ค๋ผ


๐Ÿง  ์„œ๋ฒ„ ๋กœ๊ทธ ์˜ˆ์‹œ

connected to (localhost, 33454)
server received 6 bytes
server received 13 bytes

๐Ÿ“Œ 7.1 ./echoclient localhost 8000 ์„ ์ž…๋ ฅํ–ˆ๋Š”๋ฐ ์™œ ์—‰๋šฑํ•œ ํฌํŠธ์— ์—ฐ๊ฒฐ๋˜์ง€?

์—์ฝ” ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ด๋‘๊ณ , ํด๋ผ์ด์–ธํŠธ๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ:

./echoclient localhost 8000

์„œ๋ฒ„ ์ชฝ์— ์ด๋ ‡๊ฒŒ ์ถœ๋ ฅ๋œ๋‹ค.

connected to (localhost, 43298)

๐Ÿคจ 8000 ํฌํŠธ๋กœ ์—ฐ๊ฒฐํ–ˆ๋Š”๋ฐโ€ฆ 43298์€ ๋ญ์ง€? ์™œ ์ด์ƒํ•œ ๋ฒˆํ˜ธ๊ฐ€ ์ฐํžˆ๋Š” ๊ฑธ๊นŒ?


โœ… ๊ฒฐ๋ก : ์„œ๋ฒ„ ํฌํŠธ๋Š” 8000, ํด๋ผ์ด์–ธํŠธ ํฌํŠธ๋Š” ๋žœ๋ค

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ๋•Œ,
์„œ๋ฒ„์˜ ํฌํŠธ ๋ฒˆํ˜ธ๋Š” ๋‚ด๊ฐ€ ์ง์ ‘ ์ง€์ •ํ•˜์ง€๋งŒ,
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์“ฐ๋Š” ํฌํŠธ๋Š” ์šด์˜์ฒด์ œ๊ฐ€ ์ž๋™์œผ๋กœ ์ •ํ•ด์คŒ.

์ด๊ฑธ ephemeral port (์ž„์‹œ ํฌํŠธ)๋ผ๊ณ  ํ•จ.


๐Ÿ“ฆ ์˜ˆ์‹œ ํ๋ฆ„

ํด๋ผ์ด์–ธํŠธ: 127.0.0.1:43298 โ†’ ์„œ๋ฒ„: 127.0.0.1:8000
  • ์„œ๋ฒ„๋Š” 8000๋ฒˆ ํฌํŠธ๋ฅผ ์—ด๊ณ  ๋Œ€๊ธฐ ์ค‘ (listen(8000))
  • ํด๋ผ์ด์–ธํŠธ๋Š” 43298๋ฒˆ ํฌํŠธ๋กœ ์ถœ๋ฐœํ•˜์—ฌ ์ ‘์† (connect())
  • ๊ทธ๋ž˜์„œ ์„œ๋ฒ„๋Š” "localhost:43298์—์„œ ์—ฐ๊ฒฐ๋จ"์ด๋ผ๊ณ  ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ

๐Ÿง  ํด๋ผ์ด์–ธํŠธ ํฌํŠธ๋Š” ์–ด๋–ป๊ฒŒ ์ •ํ•ด์งˆ๊นŒ?

์šด์˜์ฒด์ œ๊ฐ€ ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘์ด์ง€ ์•Š์€ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ž๋™์œผ๋กœ ํ•˜๋‚˜ ํ• ๋‹นํ•ด์ค€๋‹ค.

์ด ๋ฒ”์œ„๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

OSephemeral port ๋ฒ”์œ„
Linux32768 ~ 60999
macOS49152 ~ 65535

๐Ÿงช ์ง์ ‘ ํ™•์ธํ•ด๋ณด๊ธฐ (Linux)

cat /proc/sys/net/ipv4/ip_local_port_range

์˜ˆ์‹œ ์ถœ๋ ฅ:

32768    60999

โ†’ ์ด ๋ฒ”์œ„ ์•ˆ์—์„œ ํด๋ผ์ด์–ธํŠธ ํฌํŠธ๊ฐ€ ์ž๋™ ์„ ํƒ๋œ๋‹ค.


โœ… ์ •๋ฆฌํ•˜์ž๋ฉด

๊ฐœ๋…์„ค๋ช…
์„œ๋ฒ„ ํฌํŠธ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง€์ •ํ•จ (์˜ˆ: 8000)
ํด๋ผ์ด์–ธํŠธ ํฌํŠธOS๊ฐ€ ์ž๋™์œผ๋กœ ํ• ๋‹นํ•จ (์˜ˆ: 43298)
์™œ ํ•„์š”ํ•œ๊ฐ€?์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋™์‹œ์— ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถœ๋ฐœ์ง€๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ•จ
์ด๊ฑธ ๋ญ๋ผ๊ณ  ๋ถ€๋ฅด๋‚˜?ephemeral port (์ž„์‹œ ํฌํŠธ)

๐Ÿ“Œ ๊ฒฐ๋ก 

./echoclient localhost 8000 โ†’
"์„œ๋ฒ„์˜ 8000๋ฒˆ ํฌํŠธ๋กœ ์—ฐ๊ฒฐํ•˜๊ฒ ๋‹ค"๋Š” ๋œป์ด์ง€,
"๋‚ด ํด๋ผ์ด์–ธํŠธ ํฌํŠธ๋„ 8000์„ ์“ฐ๊ฒ ๋‹ค"๋Š” ๋œป์€ ์•„๋‹ˆ๋‹ค!

์šด์˜์ฒด์ œ๊ฐ€ ์ž๋™์œผ๋กœ ์•ˆ ๊ฒน์น˜๋Š” ์ž„์‹œ ํฌํŠธ ํ•˜๋‚˜๋ฅผ ๊ณจ๋ผ์„œ ์—ฐ๊ฒฐํ•ด์ค€๋‹ค.
๊ทธ๊ฒŒ ๋ฐ”๋กœ 43298, 39924, 55446 ๊ฐ™์€ ์ˆซ์ž๋‹ค.


๐Ÿ“Œ 7.2 ์•ŒํŒŒ๋ฒณ 5๊ธ€์ž์ธ๋ฐ ์™œ 6๋ฐ”์ดํŠธ?

์—์ฝ” ์„œ๋ฒ„ ๋กœ๊ทธ์— ์ด๋Ÿฐ ๋ฉ”์‹œ์ง€๊ฐ€ ๋œฌ๋‹ค.

server received 6 bytes

ํ•˜์ง€๋งŒ ๋‚˜๋Š” hello๋ผ๋Š” ์•ŒํŒŒ๋ฒณ 5๊ธ€์ž๋งŒ ์ž…๋ ฅํ–ˆ๋Š”๋ฐโ€ฆ
โ“ ์™œ 6๋ฐ”์ดํŠธ๊ฐ€ ๋˜๋Š” ๊ฑธ๊นŒ?


โœ… ์ด์œ ๋Š” ๋ฐ”๋กœ \n ๋•Œ๋ฌธ

ํ„ฐ๋ฏธ๋„์—์„œ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•œ ๋’ค Enter๋ฅผ ๋ˆ„๋ฅด๋ฉด,
์ปดํ“จํ„ฐ๋Š” ๋ฌธ์ž์—ด ๋์— ์ค„๋ฐ”๊ฟˆ ๋ฌธ์ž(Newline), ์ฆ‰ \n์„ ์ž๋™์œผ๋กœ ๋ถ™์ธ๋‹ค.

๊ทธ๋ž˜์„œ ์‹ค์ œ๋กœ ์„œ๋ฒ„์— ์ „๋‹ฌ๋œ ๋ฌธ์ž์—ด์€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค:

"hello\n"

๐Ÿ“ฆ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ๋ถ„์„ํ•ด๋ณด๋ฉด?

๋ฌธ์ž๋ฐ”์ดํŠธ ์ˆ˜ (UTF-8 ๊ธฐ์ค€)
h1
e1
l1
l1
o1
\n (์ค„๋ฐ”๊ฟˆ)1
ํ•ฉ๊ณ„6๋ฐ”์ดํŠธ โœ…

๐Ÿงช ์ง์ ‘ ์‹คํ—˜ํ•ด๋ณด๊ธฐ (Linux/macOS)

echo -n "hello" | wc -c     # ์ถœ๋ ฅ: 5
echo -n "hello\n" | wc -c   # ์ถœ๋ ฅ: 6

๐Ÿ“Œ -n ์˜ต์…˜์€ echo ๋ช…๋ น์ด ์ž๋™์œผ๋กœ ์ค„๋ฐ”๊ฟˆ์„ ๋„ฃ์ง€ ์•Š๋„๋ก ๋ฐฉ์ง€ํ•˜๋Š” ์˜ต์…˜.


โœ… ์š”์•ฝ

  • ์šฐ๋ฆฌ๊ฐ€ ์•ŒํŒŒ๋ฒณ 5๊ธ€์ž๋ฅผ ์ž…๋ ฅํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ,
  • ํ„ฐ๋ฏธ๋„์—์„œ๋Š” ๊ทธ ๋’ค์— \n๋„ ํ•จ๊ป˜ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๊ณ  ์žˆ์—ˆ๋˜ ๊ฒƒ!

์ฆ‰, 5๊ธ€์ž + \n = 6๋ฐ”์ดํŠธ๊ฐ€ ์„œ๋ฒ„์— ์ „์†ก๋œ ๊ฒƒ์ด๋‹ค.


โœ… ์ „์ฒด ์š”์•ฝ

๋‹จ๊ณ„ํ•œ ์ผ
๐Ÿ“ ๋””๋ ‰ํ† ๋ฆฌecho/ ํด๋” ์ƒ์„ฑ
๐Ÿ“„ ํŒŒ์ผ ์ž‘์„ฑechoserveri.c, echoclient.c, echo.c
๐Ÿ“ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌcsapp.c, csapp.h ๋ณต์‚ฌ
๐Ÿ›  Makefile์ปดํŒŒ์ผ ์ž๋™ํ™”
๐Ÿ”จ make์ปดํŒŒ์ผ ์„ฑ๊ณต
๐Ÿš€ ์‹คํ–‰์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ

โœจ ๋‚ด๊ฐ€ ๋ฐฐ์šด ๊ฒƒ

  • TCP ์—ฐ๊ฒฐ์€ socket() โ†’ connect() โ†’ read()/write() ํ๋ฆ„์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค
  • ์„œ๋ฒ„๋Š” listen()ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” connect()ํ•œ๋‹ค
  • ํ•œ๊ธ€ ์ž…๋ ฅ์€ UTF-8 ๊ธฐ์ค€ ๊ธ€์ž๋‹น 3๋ฐ”์ดํŠธ, ์ค„๋ฐ”๊ฟˆ ํฌํ•จ 4๋ฐ”์ดํŠธ
  • rio_t๋ฅผ ์“ฐ๋ฉด ๋„คํŠธ์›Œํฌ ์ฝ๊ธฐ๊ฐ€ ๋” robust ํ•ด์ง„๋‹ค
  • Makefile๊ณผ -pthread ์„ค์ •์˜ ์ค‘์š”์„ฑ
profile
์„œํˆด์ง€์–ธ์ • ๋Š˜ ํ–‰๋™์ด ๋จผ์ €์ด๊ธฐ๋ฅผ

4๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2025๋…„ 5์›” 2์ผ

ubuntu

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ

์ข‹์€ ์ •๋ณด๊ธ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค :)

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
comment-user-thumbnail
2025๋…„ 5์›” 3์ผ

๋ฒจ๋กœ๊ทธ ๊ธ€ ์Šคํฌ๋žฉํ•ด์„œ ๋ฆฌํฌ์ŠคํŒ… ํ•˜๋Š” ๊ธฐ๋Šฅ์€ ์™œ ์—†์„๊นŒ

1๊ฐœ์˜ ๋‹ต๊ธ€