01. TCP/IP 프로토콜 스택을 4개의 계층으로 구분해 보자. 그리고 TCP소켓이 거치는 계층구조와 UDP소켓이 거치는 계층구조의 차이점을 설명해보자.

-> 아래 그림을 참조한다.

1.  TCP 프로토콜 스택


2. UDP프로토콜 스택


02. TCP/IP 프로토콜 스택 중에서 LINK계층과 IP계층이 담당하는 역할이 무엇인지 설명해보자. 그리고 이 둘의 관계도 함께 설명해보자.

-> LINK 계층은 물리적인 영역의 표준화를 담당하고 있는 계층으로 LAN, WAN, MAN과 같은 네트워크 표준과 관련된 프로토콜을 정의하는 영역이다.

IP계층은 LINK계층에서 물리적 연결이 형성되었으니 목적지로 데이터를 전송하기 위해 어떤 경로를 선택할지를 해결하는 계층이다.


03. TCP/IP 프로토콜 스택을 4개의 계층(또는 7개의 계층)으로 나누는 이유는 무엇인가? 이를 개방형 시스템에 대한 설명과 함께 답해보자.

-> 표준화 작업을 통해 많은 사람들이 이 표준을 따르도록 하고 이런 표준을 근거로 설계된 시스템을 개방형 시스템이라고한다. 결과적으로 빠른속도의 기술발전이 가능하다.


04. 클라이언트는 connect함수호출을 통해서 서버로의 연결을 요청한다. 그렇다면 클라이언트는 서버가 어떠한 함수를 호출한 이후부터 connect함수를 호출할 수 있는가?

-> lisen함수


05. 연결요청 대기 큐라는 것이 생성되는 순간은 언제이며 이것이 어떠한 역할을 하는지 설명해보자. 그리고 accept함수와의 관계도 함께 설명해보자.

-> listen 함수가 호출되는 시점이다. 연결요청 대기 큐는 클라이언트의 연결요청 정보를 저장하는 대기공간으로, accept함수가 호출되면 이 공간에 있는 연결요청 정보를 참조하여 클라이언트와 연결한다.

 

06. 클라이언트 프로그램에서 소켓에 주소정보를 할당하는 bind 함수호출이 불필요한 이유는 무엇인가? 그리고 bind 함수를 호출하지 않았을 경우, 언제 어떠한 방식으로 IP주소와 PORT번호가 할당되는가?

-> 연결을 요청할 서버의 주소정보가 중요하기 때문에 bind함수로 주소정보를 할당할 필요는 없는데 서버와 연결하려면 소켓에 주소정보를 할당해야한다.

만약 bind함수를 호출 하지 않았을 때 connect함수호출 시 소켓에 자동으로 IP와 포트번호가 할당된다.


07. Chapter 01에서 구현한 예제 hello_server.c와 hello_server_win.c를 iterative 모델로 변경하고, 제대로 변경되었는지 클라이언트와 함께 테스트해보자.

-> 리눅스 기반 서버와 클라이언트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdio.h>
#include <stdlib.h>
#include <sting.h>
#include <unistd.h>
#include <srpa/inet.h>
#include <sys/socket.h>
void error_handling(char *message);
int main(int argc, char *argv[])
{
        int serv_sock;
        int clnt_sock;
        struct sockaddr_in serv_addr;
        struct sockaddr_in clnt_addr;
        socklen_t clnt_addr_size;
        char message[] = "Hello World!";
        if (argc != 2)
        {
               printf("Usage:%s <port>\n", argv[0]);
 
               exit(1);
        }
 
        serv_sock = socket(PF_INET, SOCK_STREAM, 0);
        if (serv_sock == -1)
               error_handling("socket() error");
        memset(&serv_addr, 0sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_addr.sin_port = htons(atoi(argv[1]));
        if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1
               error_handling("bind() error");
        if (listen(serv_sock, 5== -1
               error_handling("listen() error");
 
        clnt_addr_size = sizeof(clnt_addr);
        while (1
        {
               clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);                                                                                                           
               if (clnt_sock == -1)
                       error_handling("accept() error");
               write(clnt_sock, message, sizeof(message)); 
               close(clnt_sock);
        }
        close(serv_sock);
        return 0;
}
void error_handling(char *message)
{
 
        fputs(message, stderr);
        fputc('\n', stderr);
        exit(1);
 
}
cs


'열혈 TCP IP 소켓 프로그래밍' 카테고리의 다른 글

Chapter03 내용 확인 문제  (0) 2020.06.20
Chapter02 내용 확인문제  (0) 2020.06.19
Chapter01 내용 확인문제  (0) 2020.06.19

+ Recent posts