1. 스레드 기초
1) 소켓 응용 프로그램과 멀티 스레드
● TCP 서버 - 클라이언트의 문제점
- 클라이언트 2개 이상이 서버에 접속할 수는 있으나, "서버가 동시에 클라이언트 2개 이상에 서비스할 수 없다."
- 서버와 크라이언트의 send(), recv()함수의 호출 순서가 맞아야한다.
- 데이터를 보내지 않은 상태에서 양쪽에서 동시에 recv()함수를 호출하면 교착 상태가 발생할 수 있다.
● 1번 문제의 해결방법들과 장단점
방법1. 서버가 각 클라이언트와 연결해 통신하는 시간을 짧게 줄인다.
- 클라언트가 데이터를 전송하기 전에 매번 서버에 접속하고, 전송 후에는 곧바로 접속을 끊는 방식
- 장점
- 쉽게 구현 가능
- 서버의 시스템 자원을 적게 사용
- 단점
- 파일 전송 프로그램과 같이 대용량 데이터를 전송하는 응용프로그램에는 적합하지 않음
- 클라이언트 수가 많을 경우 처리 지연시간이 길어질 확률이 높다. (처리의 효율성 Down)
방법2. 서버에 접속한 각 클라언트를 스레드를 이용해 독립적으로 처리한다.
- 장점
- 소켓 입출력 모델(아래의 방법)에 비해 비교적 쉽게 구현 가능
- 단점
- 접속한 클라이언트 수에 비례해 스레드를 생성하므로 서버의 시스템 자원을 많이 사용한다.
방법3. 소켓 입출력 모델을 사용
- 장점
- 소수의 스레드를 이용해 다수의 클라이언트를 처리할 수 있다. 따라서 2번째 방법보다 서버의 시스템 자원을 적게 사용한다.
- 단점
- 위의 2방법보다 구현이 어렵다.
● 2번 문제의 해결방법들과 장단점(교착상태 발생 가능)
방법1. 데이터 송수신 부분을 잘 설계해 교착 상태가 발생하지 않게한다.
- 장점
- 특별한 기법을 도입하지 않고도 구현가능
- 단점
- 데이터 송수신 패턴에 따라 교착 상태가 발생할 수 있다. 따라서 이 방법을 모든 경우에 적용할 수는 없다.
방법2. 소켓에 타임아웃(timeout)옵션을 적용해, 소켓 함수 호출시 작업이 완료되지 않아도 일정 시간 후에 리턴하게 한다.
- 장점
- 비교적 간단한 구현
- 단점
- 기다려야 하기 때문에 다른 방법보다 성능이 떨어진다.
방법3. 넌블로킹(nonblocking) 소켓을 이용한다.
- 논블로킹이란, 근본적으로 교착상태를 해결할 수 있는 방법이다.
- 시스템에 교착상태가 일어났는지 안일어났는지를 계속해서 모니터링하는 방법이다.
- 장점
- 교착 상태를 막을 수 있다.
- 단점
- 구현이 복잡하다. 시스템 자원(특히 CPU 시간)을 불필요하게 방비할 가능성이 크다.
방법4. 소켓 입출력 모델을 사용한다.
- 장점
- 넌블로킹 소켓의 단점을 보완함과 더불어 교착 상태를 막을 수 있다.
- 단점
- 1,2 번 방법보다 구현이 어렵다. 그러나 3번째 방법보다는 쉬고 일관성 있게 구현할 수 있다.
2) 스레드 기본 개념
운영체제관점에서,
프로세스는 CPU시간을 할당받아 실행 중인 프로그램을 말한다.
프로그램이 저장 장치에 파일로 존재하는 정적인 개념이고
프로세스느 동적인 개념이다.
윈도우 운영체제관점에서는,
프로세스 개념을 프로세스와/ 스레드 두개로 구분한다.
● 프로세스와 스레드
- 프로세스
- 코드, 데이터, 리소스를 파일에서 읽어들여 윈도우 운영체제 가 할당해놓은 메모리 영역에 담고 있는 일종의 컨테이너로 정적인 개념
- 스레드
- CPU 시간을 할당받아 프로세스 메모리 영역에 있는 코드를 수행하고 데이터를 사용하는 동적인 개념
- 주 스레드 or 메인 스레드
- 응용 프로그램 실행 시 최초로 생성되는 스레드 – WinMain() 또는 main() 함수에서 실행 시작
- 컨텍스트 전환
- CPU가 2개 이상의 스레드를 동시에 실행은 불가능하지만 교대로 실행이 가능하다.
- 교대로 실행하는 간격이 짧다면 두 스레드가 동시에 실행되는 것 처럼 느껴진다.
- 이렇게 하려먼 각 스레드의 최종 실행 상태를 저장하고 나중에 복원하는 작업을 해야한다.
- 스레드 실행 상태의 저장과 복원잡업을 컨텍스트 전환이라고 한다.
● 멀티스레드 동작 원리
(a) 스레드 (1) 실행
(b) 컨텍스트 전환 (1~2)
(c) 스레드 (2) 실행
(d) 컨텍스트 전환(2->1)
(e) 스레드 (1) 실행
3) 스레드의 생성과 종료
● 스레드 생성에 필요한 요소
프로세스가 생성되면 main()함수를 실행 시작점으로 하는 주 스레드가 자동으로 생성된다.
이때 또 다른 함수인 f()를 실행 시작점으로 하는 스레드를 생성하려면 다음과 같은 정보를 운영체제에 제공해야 한다.
- 스레드 함수의 시작주소 ( f( ) 함수의 시작 주소)
- 운영체제는 f()함수의 시작 주소를 알아야 한다.
- f( ) 함수와 같이 스레드 실행 시작점이 되는 함수를 스레드 함수라 한다.
- 스레드 함수 실행 시 사용할 스택의 크기
- c/c++ 프로그램의 모든 함수는 실행 중 인자 전달과 변수 할당을 위해 스택이 필요하다.
- f( )함수를 실행 시작점으로 하는 스레드 2개를 생성하고자 한다면, 서로 다른 메모리 위치에 스택 두개를 할당해야 한다.
- 스레드 실행에 필요한 스택 생성은 자동으로 생성되므로, 스택의 크기만 알려주면 된다.
● 스레드 생성 함수
CreateThread() 함수
: 스레드 생성 후 스레드 핸들을 리턴
HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpThreadAttributes, // NULL
SIZE_T dwStackSize, // 0
LPTHREAD_START_ROUTINE lpStartAddress, // 스레드 함수
LPVOID lpParameter, // 스레드 함수에 전달할 인자
DWORD dwCreationFlags, // 0 또는 CREATE_SUSPENDED
LPDWORD lpThreadId // 스레드 ID
) ;
성공: 스레드 핸들, 실패: NULL
스레드 함수 형태
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
...
}
● 스레드 종료 방법
- 스레드 함수가 리턴
- 스레드 함수 내에서 ExitThread() 함수를 호출
- 다른 스레드가 TerminateThread() 함수를 호출
- 주 스레드가 종료하면 모든 스레드가 종료
스레드 종료 함수
void ExitThread (
DWORD dwExitCode // 종료 코드
) ;
BOOL TerminateThread (
HANDLE hThread, // 종료할 스레드를 가리키는 핸들
DWORD dwExitCode // 종료 코드
) ;
성공: 0이 아닌 값, 실패: 0
4) 스레드 제어
스레드는 윈도우 운영체제의 실행 단위므로, 우선순위를 변경하거나 실행을 중지하고 재시작하는 등의 제어 기능을 윈도우 API수준에서 지원한다.
● 스레드 우선순위 변경
- 스레드 스케줄링 or CPU 스케줄링
- 윈도우 운영체제가 각 스레드에 CPU 시간을 적절히 분배하 기 위한 정책
- 우선순위 클래스
- 프로세스 속성으로, 같은 프로세스가 생성한 스레드는 우선 순위 클래스가 모두 같음
- 우선순위 레벨
- 스레드 속성으로, 같은 프로세스에 속한 스레드 간 상대적인 우선순위를 결정할 때 사용
- 기본 우선순위
- 우선순위 클래스와 우선순위 레벨을 결합한 값으로, 스레드 스케줄링에 사용
● 우선순위 클래스
REALTIME_PRIORITY_CLASS(실시간)
HIGH_PRIORITY_CLASS(높음)
ABOVE_NORMAL_PRIORITY_CLASS(높은 우선순위; 윈도우 2000 이상)
NORMAL_PRIORITY_CLASS(보통)
BELOW_NORMAL_PRIORITY_CLASS(낮은 우선순위; 윈도우 2000 이상)
IDLE_PRIORITY_CLASS(낮음)
● 우선순위 레벨
THREAD_PRIORITY_TIME_CRITICAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_IDLE
● 윈도우의 스레드 스케줄링 방식
- 기본 우선순위 : 우선순위 클래스와 우선순위 레벨을 결합하면 스레드의 기본 우선순위가 결정된다.
- 이 값이 스레드 스케줄링에 사용되는데, 우선순위가 가장 높은 스레드에 CPU시간을 할당한다.
- 우선순위 같은 스레드가 여러 개 있을 경우 CPU 시간을 번갈아 가며 할당한다.
'TCP-IP 윈도우 소켓 프로그래밍' 카테고리의 다른 글
[TCP/IP] 5장. 데이터 전송하기 (0) | 2021.04.14 |
---|---|
[TCP/IP] 4장. TCP 서버- 클라이언트 (0) | 2021.04.09 |
[TCP/IP] 3장. 소켓 주소 구조체 다루 (0) | 2021.04.09 |
[TCP/IP] 2장. 윈도우 소켓 시작하기 (0) | 2021.04.07 |
[TCP/IP] 1장. 네트워크와 소켓 프로그래밍 (0) | 2021.04.06 |