본문 바로가기
Develop/Network

[윤성우의 열혈 TCP/IP 소켓 프로그래밍] Chapter23 - 내용 확인 문제 풀이

by Tarra 2023. 7. 2.

 

 

 

 

 [윤성우의 열혈 TCP / IP 소켓 프로그래밍] 책을 기반으로 개인적으로  문제 풀이 및 개념을 정리한 내용입니다.

모든 소스 코드와 강의, 확인 문제의 정확한 답안은 (23년 7월 1일부터 전면 무료화 예정)

http://www.orentec.co.kr/

 

====== 오렌지 미디어 ======

 

www.orentec.co.kr

에서 확인할 수 있습니다.

 

 


 

 

01. Completion Port 오브젝트에는 하나 이상의 쓰레드가 할당되어서 입출력을 처리하게 된다. 그렇다면 Completion Port 오브젝트에 할당될 쓰레드는 어떻게 생성되며, 또 할당의 방법은 무엇인지 소스코드 레벨에서 설명해보자.

Completion Port 오브젝트에 할당되는 쓰레드는 개발자가 직접 생성하고 할당해야 한다.

이를 위해 일반적으로 CreateThread 함수를 사용하여 쓰레드를 생성한다.

쓰레드를 생성할 때는 쓰레드 함수와 함께 필요한 매개변수를 전달해야 한다.

 

생성된 쓰레드는 Completion Port 오브젝트와 관련된 입출력 작업을 처리하기 위해 대기 상태에 들어간다.

이때 할당의 방법은 GetQueuedCompletionStatus 함수를 사용하여 입출력 작업이 완료되면 해당 쓰레드에 작업완료를 알리는 방식이다.

 

다음은 Completion Port 오브젝트에 쓰레드를 할당하는 예시 코드이다.

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
// 쓰레드 함수 (쓰레드의 진입점)
DWORD WINAPI ThreadProc(LPVOID lpParam) {
    HANDLE hCompletionPort = (HANDLE)lpParam;
    DWORD dwBytesTransferred;
    ULONG_PTR dwCompletionKey;
    LPOVERLAPPED lpOverlapped;
 
    while (true) {
        // 입출력 작업 완료 대기
        BOOL bResult = GetQueuedCompletionStatus(hCompletionPort, 
                &dwBytesTransferred, &dwCompletionKey, &lpOverlapped, INFINITE);
 
        if (bResult) {
            // 입출력 작업이 완료된 경우 처리
            // ...
        }
        else {
            // 입출력 작업 실패 또는 오류 발생 경우 처리
            // ...
        }
    }
 
    return 0;
}
 
int main() {
    // Completion Port 오브젝트 생성
    HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL00);
    
    // 쓰레드 생성 및 할당
    for (int i = 0; i < NUM_THREADS; ++i) {
        HANDLE hThread = CreateThread(NULL0, ThreadProc, hCompletionPort, 0NULL);
        // ...
    }
 
    // 입출력 작업 등록
    // ...
 
    // 프로그램 실행
    // ...
 
    return 0;
}
 
cs

 

더보기

모범 답안

Completion Port 오브젝트에 할당될 쓰레드는 프로그래머에 의해서 생성되어야 한다.

그리고 이렇게 생성된 쓰레드는 Completion Port 오브젝트의 핸들을 전달받아서

GetQueuedCompletionStatus 함수를 호출함으로 인해서 Completion Port 오브젝트에 할당이 된다.

즉, Completion Port 오브젝트의 할당은 소스코드의 레벨에서 보면 GetQueuedCompletionStatus 함수의 호출을 의미한다.

단, Completion Port 오브젝트를 생성할 때 지정한, CP 오브젝트에 할당할 최대 쓰레드의 수를 넘어서는 쓰레드가 

이 함수를 호출하더라도 응답을 받는 쓰레드의 수는 Completion Port 오브젝트를 생성할 때 지정한 최대 쓰레드의 수로 제한된다.

 

 

02. CreateCompletionPort 함수는 다른 함수들과 달리 두 가지의 기능을 제공한다. 그렇다면 이 두 가지 기능은 각각 무엇인가?

1. Completion Port 오브젝트의 생성

CreateCompletionPort 함수는 새로운 Completion Port 오브젝트를 생성한다.

이 함수를 호출하여 새로운 Completion Port 오브젝트를 만들 수 있다.

 

2. I/O 디바이스와의 연결

CreateCompletionPort 함수는 I/O 디바이스와 생성된 Completion Port 오브젝트를 연결한다.

이를 통해 I/O 작업의 완료 알림을 받을 수 있는 메커니즘을 설정한다.

CreateCompletionPort 함수는 I/O 디바이스와 Completion Port 오브젝트를 연결하기 위해 사용되는 함수이다.

 

더보기

모범 답안

Completion Port 오브젝트의 생성, Completion Port 오브젝트와 소켓과의 연결.

 

 

03. Completion Port 오브젝트와 소켓의 연결이 의미하는 바는 무엇인가? 그리고 연결의 과정은 어떻게 진행해야 하는가?

Completion Port 오브젝트와 소켓의 연결은 소켓 I/O 작업의 완료 알림을 받기 위한 메커니즘을 설정하는 것을 의미한다.

연결을 통해 I/O 작업이 완료되면 Completion Port 오브젝트에 알림이 전달되어 처리될 수 있다.

 

1. Completion Port 오브젝트 생성

CreateIoCompletionPort 함수를 사용하여 Completion Port 오브젝트를 생성한다.

 

2. 소켓과의 연결

WSASocket 함수를 사용하여 소켓을 생성한다.

이후, CreateIoCompletionPort 함수를 사용하여 소켓을 생성된 Completion Port 오브젝트에 연결한다.

이를 통해 소켓의 I/O 작업 완료 알림을 받을 수 있게 된다.

 

3. 비동기 I/O 작업 수행

연결된 소켓에서 비동기 I/O 작업을 수행한다.

이때, 비동기 I/O 함수인 ReadFile, WriteFile 등을 사용하여 I/O를 수행하고, GetQueuedCompletionStatus 함수를 사용하여 I/O 작업의 완료 상태를 확인한다.

 

4. I/O 작업 완료 알림 처리

GetQueuedCompletionStatus 함수를 호출하여 I/O 작업의 완료 알림을 기다린다.

해당 함수가 반환하는 결과를 통해 완료된 I/O 작업에 대한 정보를 얻고, 이에 따른 후속 작업을 진행한다.

 

더보기

모범 답안

먼저 CreateIoCompletionPort 함수호출을 통해서 Completion Port 오브젝트를 생성한다.

그 다음 다시 CreateIoCompletionPort 함수를 호출해서, 인자로 전달되는 핸들의 소켓에, 완료된 IO의 정보가,

먼저 생성한 Completion Port 오브젝트에 등록되도록 한다.

바로 이것이 CP 오브젝트와 소켓과의 연결이 의미하는 바다.

 

 

04. IOCP와 관련된 다음 문장들 중에서 옳지 않은 것을 모두 고르면?

a. 최소한의 쓰레드로 다수의 IO를 처리할 수 있는 구조이기 때문에 쓰레드의 컨텍스트 스위칭으로 인한 성능의 저하를 막을 수 있다.

 

b. IO가 진행중인 상태에서 서버는 IO의 완료를 기다리지 않고, 다른 일을 진행할 수 있기 때문에 CPU를 효율적으로 사용할 수 있는 구조이다.

 

c. IO가 완료되었을 때, 이와 관련된 Completion Routine이 자동으로 호출되기 때문에 IO의 완료를 대기하기 위해서 별도의 함수를 호출할 필요가 없다.

IOCP에서는 GetQueuedCompletionStatus 함수를 호출하여 IO의 완료를 대기하고 처리해야 한다.

따라서 IO의 완료를 대기하기 위해서는 별도의 함수를 호출해야 한다.

 

d. IOCP는 윈도우 이외의 다른 운영체제에서도 제공되는 기능이기 때문에 호환성에 있어서도 높은 점수를 줄 수 있다.

IOCP는 윈도우 운영체제에서만 지원되는 기능이다.

 

정답 c, d

 

 

05. 다음 문장들 중에서 IOCP에 할당할 적정 쓰레드의 수를 결정하는 방법으로 적절하면 O, 적절치 않으면 X를 표시해보자.

- 일반적인 선택은 CPU와 동일한 수의 쓰레드를 할당하는 것이다. (O)

- 가장 좋은 방법은 여건이 허락하는 범위 내에서 실험적인 결과를 통해서 쓰레드의 수를 결정하는 것이다. (O)

- 할당할 쓰레드의 수는 여유 있게 선택하는 것이 좋다. 예를 들어서 한 개의 쓰레드로 충분한 상황에서는 여유 있게 세 개 정도의 쓰레드를 IOCP에 할당하는 것이 좋다. (X)

 

 

06. 이번 Chapter에서 설명한 IOCP 모델을 바탕으로 채팅 서버를 구현해보자. 이 채팅 서버는 Chapter 20에서 소개한 채팅 클라이언트인 chat_clnt_win.c와 함께 동작이 가능해야 한다. 참고로 본문에서 제시한 IOCP 예제는 하나의 사례일 뿐이니, 이 틀이 꼭 맞추려고 노력하지 않아도 된다. 이 틀에 완벽히 맞추려다보면 오히려 구현이 어렵게 느껴질 수 있다.

 

(생략)

 

 

 


출처 : [윤성우의 열혈 TCP / IP 소켓 프로그래밍] / 윤성우 저 / 오렌지 미디어

https://cafe.naver.com/cstudyjava

 

윤성우의 프로그래밍 스터디그룹 [C/... : 네이버 카페

윤성우의 스터디 공간입니다. C와 JAVA를 공부하시는 분들은 모두 들어오세요. ^^

cafe.naver.com