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


01. IP주소 체계인 IPv4와 IPv6의 차이점은 무엇인가? 그리고 IPv6의 등장 배경은?

-> IPv4는 4바이트 주소체계, IPv6는 16바이트 주소체계이다. 현재 범용적으로 사용되고있는 주소체계는 IPv4로, IPv6는 IPv4기반의 IP주소가 모두 고갈될 것을 염려하여 만들어진 표준인데, 아직 범용화되지않았다. 



02. 회사의 로컬 네트워크에 연결되어 있는 개인 컴퓨터에 데이터가 전송되는 과정을, IPv4의 네트워크 ID와 호스트ID, 그리고 라우터의 관계를 기준으로 설명하라.

-> 네트워크 ID를 이용해 해당 네트워크(라우터 or 스위치)로 데이터가 전송되고 호스트 ID를 이용해 호스트에게 데이터를 전송한다.


03. 소켓의 주소는 IP와 PORT번호 두 가지로 구성된다. 그렇다면 IP가 필요한 이유는 무엇이고 PORT번호가 필요한 이유는 또 무엇인가? 

즉, IP를 통해서 구분되는 대상은 무엇이고 PORT번호를 통해 구분되는 대상은 무엇인가?

-> IP를 이용해 호스트로 데이터가 전송되고 호스트 내의 어떤 소켓에 전송할 지 는 포트번호를 이용해 운영체제가 데이터를 적절히 분배한다.

즉, IP는 호스트를 구분하고 포트번호는 호스트 내의 소켓을 구분하는데 사용된다.


04. IP주소의 클래스를 결정하는 방법을 설명하고 이를 근거로 다음IP주소들이 속하는 클래스를 판단해보자.

-> 네트워크ID(네트워크의 구분을 위한 IP주소의 일부)와 호스트ID의 형태에 따라 분류된다. IP주소의 첫 번 째 바이트만 확인하여 네트워크 주소가 몇바이트인지 판단 가능하다. 

클래스 A의 첫 번째 바이트 범위: 0~127

클래스 B의 첫 번째 바이트 범위: 128~191

클래스 C의 첫 번째 바이트 범위: 192~223




a. 214.121.212.101 

-> 클래스C

b. 120.101.122.89

-> 클래스 A

c. 129.78.102.211

-> 클래스 B


05. 컴퓨터는 라우터 또는 스위치라 불리는 물리적인 장치를 통해 인터넷과 연결된다. 그렇다면 라우터 또는 스위치의 역할은 무엇인가?

-> 목적지로 데이터를 전달하는데 중간 매개체 역할을 한다. ( 데이터 전송 -> 라우터 -> 호스트)


06. Well-known PORT는 무엇이며 그 값의 범위는 어떻게 되는가? 

-> 포트 번호는 2바이트로 표현되기 때문에 0~65535까지 사용할 수 있다. 그런데 well-known PORT는 0부터 1023까지의 특정 프로그램에 할당하기로 예약되어있는 포트번호다. 따라서 이 범위의 값을 제외한 다른 값을 할당해야한다.


07. 소켓에 주소를 할당하는 bind함수의 두번 째 인자는 sockaddr*형 변수인데 실제로 함수를 호출할 때는 sockaddr_in의 변수를 사용한다.(sockaddr*형으로 형 변환해 사용) 그 이유는 무엇인가?

-> sockaddr 구조체는 IP번호와 PORT번호를 할당하기 쉽지 않은 구조다. 그렇기 때문에 IP주소와 PORT번호 할당이 용이한 sockaddr_in 구조체가 사용된다. 형변환해서 사용하는 이유는 sockaddr_in구조체를 이용하여 IP주소와 PORT번호를 할당하면 이 구조체 변수의 바이트 열은 sockaddr과 동일하므로 

주소 정보를 할당하기 편한 sockaddr_in을 이용한다. bind 함수의 동작은 sockaddr형 구조체를 이용하므로 sockaddr_in구조체를 이용하여 주소정보를 할당 한 후 sockaddr형으로 형변환하여 사용한다.



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

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


01. 프로토콜이란 무엇을 의미하는가? 그리고 데이터의 송수신에 있어서 프로토콜을 정의한다는 것은 어떠한 의미가 있는가?

-> 컴퓨터 상호간의 대화에 필요한 통신 규약을 의미한다. 데이터의 송수신에 있어서 프로토콜을 정의하는 것은 데이터를 주고받기 위해 정의해 놓은 약속을 의미한다.


02. 연결지향형 소켓인 TCP소켓의 전송 특성 세가지를 나열하라.

-> 전송 중간에 데이터가 소멸되지않고 목적지로 전송됨, 전송 데이터가 순서대로 전송됨, 전송 데이터의  경계가 없음(read함수 횟수와 write함수 횟수가 다름)


03. 다음 중 비 연결지향형 소켓의 특성에 해당하는 것을 모두 고르면?

->a, c, e

a. 전송된 데이터는 손실될 수 있다.

b. 데이터의 경계가 존재하지 않는다.

c. 가장 빠른 전송을 목표로한다.

d. 한번에 전송할 수 있는 데이터의 크기가 제한되어 있지 않다.

e. 연결지향형 소켓과 달리 연결이라는 개념이 존재하지 않는다.


04. 다음 유형의 데이터 송수신에 적합한 타입의 소켓은 무엇인지 결정하고, 그러한 결정을 하게 된 이유를 설명해보자.

a. 서태지와 아이들의 실시간 라이브 방송 멀티미디어 데이터

-> UDP: 데이터 손실의 중요성이 떨어지고 전송속도가 중요함

b. 철수가 압축한 텍스트 파일의 전송

-> TCP: 압축파일은 데이터가 손상되면 안됨

c. 인터넷 뱅킹을 이용하는 고객과 은행 사이에서의 데이터 송수신

-> 은행거래는 1:1로 해야하고 데이터가 손실되면 안됨


05. 데이터의 경계가 존재하지 않는 소켓은 어떠한 타입의 소켓인가? 그리고 이러한 소켓은 데이터를 수신할 때 무엇을 주의해야하는가?

-> TCP, 전송되는 데이터의 경계가 존재하지않기 때문에 전송 데이터와 수신 데이터의 양이 같아야한다. 


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

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


01. 네트워크 프로그래밍에서 소켓이 담당하는 역할이 무엇인가? 그리고 소켓이라는 이름이 붙은 이유는 어디에 있는가?

-> 물리적으로 연결되어있는 네트워크 상에서 데이터 송수신에 사용할 수 있는 소프트웨어적인 장치역할을 하고, 멀리 떨어져있는 컴퓨터와 데이터를  송수신하려면 인터넷 망에 연결해야하는데 프로그래밍에서 소켓은  네트워크 망에 연결에 사용되는 도구로 사용되므로 '연결'이라는 의미가 담겨있어서 소켓이라는 표현을 사용한다. 

* 물리적 연결: 직접 연결과 인터넷(네트워크) 연결



02. 서버프로그램에서는 소켓생성 이후에 listen함수와 accept함수를 차례대로 호출한다. 그렇다면 이들의 역할은 각각 무엇인지 비교해서 설명해보자.

-> listen함수 호출 시 클라이언트가 서버에 연결을 요청 할 수 있는 상태가 되고 이어서 accept함수 호출 시 서버가 클라이언트의 연결 요청을 받아들이며 서버와 클라이언트의 연결이 완료된다.

 

03. 리눅스의 경우 파일 입출력 함수를 소켓 기반의 데이터 입출력에 사용할 수 있다. 반면 윈도우에서는 이것이 불가능하다. 그렇다면 리눅스에서는 가능하고, 윈도우에서는 불가능한 이유가 무엇인가?

-> 리눅스는 파일과 소켓이 같다. 즉, 소켓도 파일로 간주하기 때문에 파일 입출력 함수를 소켓 기반의 데이터 입출력에 사용할 수 있다.

윈도우는 소켓과 파일이 구분되기 때문에 파일입출력과 소켓입출력이 구분된다.


04. 소켓을 생성한 다음에는 주소할당의 과정을 거친다. 그렇다면 주소할당이 필요한 이유는 무엇이며, 이를 목적으로 호출하는 함수는 또 무엇인가?

-> IP주소와 포트넘버를 할당하는데, IP는 컴퓨터를 구분하는 목적으로 사용되고 포트넘버는 컴퓨터로 전송된 데이터를 소켓에 전달해주는데 사용된다.

즉 IP주소는 컴퓨터를 구분하고 포트넘버는 소켓을 구분하기 위해 사용되고 이 정보를 이용해 데이터를 주고 받기 때문에 생성한 소켓에  bind함수로 주소를 할당하는 과정을 거친다.


05. 리눅스의 파일 디스크립터와 윈도우의 핸들이 의미하는 바는 사실상 같다. 그렇다면 이들이 의미하는 바가 무엇인지 소켓을 대상으로 설명해보자.

-> 리눅스의 파일 디스크립터와 윈도우의 핸들은 소켓을 구분하고 지정하는 목적으로 소켓에 부여된 정수값이다.


06. 저 수준 파일 입출력과 ANSI표준에서 정의하는 파일 입출력 함수는 어떠한 차이가 있는가?

-> 저 수준 파일 입출력 함수는 운영체제 별로 정의하는 형태가 다르고, ANSI표준에서 정의하는 파일 입출력은 C언어 기반의 표준 라이브러리 함수이므로  모든 운영체제에서 사용가능하다.


07. 저수준 파일 입출력 함수와 ANSI표준 입출력함수를 기반으로 파일 복사 프로그램을 작성하시오.


-> 저수준 파일 입출력

2행은 open 함수를 위한 헤더, 3행은 read, write함수를 위한 헤더다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define BUF_SIZE 100
int main(int argc, int argv[])
{
        int file1, file2;
        char buf[BUF_SIZE];
        int read_cnt;
        file1 = open("file1.txt", O_RDONLY); 
        file2 = open("file2.txt", O_CREAT | O_WRONLY | O_TRUNC);
        if (file1 == -1 || file2 == -1)
        {
               puts("open() error!!");
               return 0;
        }
        while ((read_cnt = read(file1, buf, BUF_SIZE)) != 0)
               write(file2, buf, read_cnt); 
        close(file1);
        close(file2);
        return 0;
}
 
cs


-> ANSI표준 파일 입출력
자주 쓰이는 형태이므로 익혀둘 필요가 있음
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
#include <stdio.h>
#define BUF_SIZE 100
int main(void)
{
        char buf[BUF_SIZE];
        int read_cnt;
        FILE *file1 = fopen("file1.txt""rb"); 
        FILE *file2 = fopen("file2.txt""wb"); 
        if (file1 == NULL || file2 == NULL;
 
        {
               puts("fopen() error");
               return 0;
        }
        while (1)
        {
               read_cnt = fread((void*)buf, 1, BUF_SIZE, file1); /
               if (read_cnt < BUF_SIZE)  //읽어온 데이터는 버퍼 사이즈를 넘을 수 없음
               {
                       if (feof(file1) != 0//파일의 끝에 도달= 0이아닌 값
                       {
                              fwrite((void*)buf, 1, read_cnt, file2);
                              break;
                       }
                       else
                              puts("복사 오류");
                       break;
               }
        }
        fclose(file1);
        fclose(file2);
        return 0;
}
cs


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

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

+ Recent posts