파이톨치

[socket programming] IO multiplexing 본문

대학수업/socket programming

[socket programming] IO multiplexing

파이톨치 2024. 4. 20. 00:13
728x90

멀티프로세스 서버의 단점과 대안

멀티프로세스 서버의 단점

프로세스의 빈번한 생성은 성능의 저하이어진다.

멀티 프로세스의 흐름을 고려해서 구현해야 하기 때문에 구현이 쉽지 않다

프로세스간 통신이 필요한 상황에서는 서버의 구현이 복잡해진다. 

 

멀티프로세스 서버의 대안

하나의 프로세스가 다수의 클라이언트에게 서비스있도 록한다. 

이를 위해서는 하나의 프로세스가 여러 개의 소켓을 핸들링 있는 방법이 존재해야 한다. 바로 이것이 IO 멀티플렉싱(multiplexing)이다. 

 

멀티쓰레드/멀티프로세스 vs 입출력다중화

입출력 다중화 방식에서는 하나의 프로세스 안에서 여러 개의 소켓 IO처리


소켓 입출력 모델

소켓모드

블로킹 소켓과 넌블로킹 소켓으로구분

 

블로킹 소켓

소켓 함수 호출조건이 만족되지 않으면 함수가 리턴하지 않고 스레드 실행이 정지

조건을 만족하면 소켓 함수가 리턴하고 정지된 스레드가 실행을 재개

accept(serv_sock, (struct sockaddr*) &clnt_adr, sizeof(clnt_adr)), connet(clnt_sock, (struct sockaddr*)&serv_sock, sizeof(serv_sock)), sendto(serv_sock, message, str_len, 0, (struct sockaddr *) &clnt_adr, &clnt_adr_sz); recvfrom(serv_sock, message, BUF_SIZE-1, 0, NULL, 0); 

 

넌블로킹 소켓

소켓 함수 호출조건을 만족하지 않더라도 함수가 리턴하므로 스레드가 중단없이 다음드를 수행.

socket() 함수는기본적으로 블로킹 소켓을 생성함.

넌블로킹 소켓이 필요하면 fcntl(sock) 함수를 호출해 소켓모드를 변경해야함.

 

넌블로킹 소켓과 소켓 함수

넌블로킹 소켓에 대해 소켓 함수 호출조건을 만족하지 않으면 소켓함수는 오류를 리턴

errno 전역 변수를 이용하여 오류코드를 확인

대개 오류 코드는 WSAEWOULDBLOCK  (return code 10035 resource temporarily unavailable) 조건을 만족하지 않았음을 나타내므로 나중에 다시 소켓 함수를 호출하면

 

넌블로킹소켓의특징

교착 상태가 생기지 않는다. 여러 소켓에 대해 돌아가며 입출력 처리 가능하고, 중간에 소켓과 관련 없는 작업도 가능함. 하지만, 소켓 함수 호출 시 오류 코드 확인해야 해서 구조 복잡해지고, CPU 사용률이 높다

 

반복서버

여러 클라이언트를 번에 하나씩 처리, 한 개 쓰레도로 구현 자원 소모 적다. 한 클라 시간 길어지면 대기 시간 증가

 

<-> 병행서버

여러 클라이언트를 동시에 처리, 한 클라 시간 길어져도 대기 시간 영향 없지만, 쓰레드 생성해야 해서 자원 소모 큼 

 

이상적인 서버의기능

가능한 많은 클라이언트접속 가능

서버는 클라이언트의 서비스 요청에 빠르게 반응하며 고속으로 데이터를 전송

시스템 자원 사용량을 최소화

 

이상적인 소켓 입출력 모델의 특징

소켓 함수 호출블로킹을 최소화

스레드 개수를 일정 수준으로 유지

CPU 명령수행과 입출력 작업을 병행

유저모드와 커널모드 전환 횟수를 최소화


select 함수의이해와서버의구현

Select 모델소개

소켓 상태 정보를 응용프로그램에관리

select() 함수가 핵심적인 역할을

소켓모드(블로킹, 넌블로킹)관계없이 여러소켓을 스레드로 처리가능

 

핵심원리

소켓함수 호출이 성공할 있는 시점을 미리 있어소켓함수 호출 (socket(PF_INET, SOCK_DGRAM, 0))조건만족하않아 생기는 문제를 해결있음

 

블로킹소켓: 소켓함수 호출조건을 만족하지 않아 블로킹되는 상황을 방지

넌블로킹소켓: 소켓함수 호출조건을 만족하지 않아 나중에 다시 호출해야 하는 상황을 방지

 

소켓들중에서 IO준비된 소켓을 미리 탐색하는 함수, 리턴된 소켓들은 IO준비된 소켓임.

 

select 함수의기능과호출순서

select 함수를 이용하면, 배열에 저장다수의 파일 디스크립터를 대상이와 같은 질문을 던질있다. (수신 데이터 지닌 소켓? 블록킹되지 않고 데이터 전송 가능 소켓? 예외 상황 발생 소켓?)

 

Step One에서는 관찰 대상(읽기, 쓰기, 예외 셋)을 묶고, 관찰의 유형을 지정한다.

Step Two에서는 관찰 대상의 변화를 묻는다.

Step Three에서는 물음에 대한 답을 듣는다.

 

파일 디스크립터의 설정

fd_set set;

모두 0으로 초기화(FD_ZERO(&set)); 

디스크립터1관찰 대상으로 추가 (FD_SET(1, &set);)

디스크립터2관찰 대상으로 추가 (FD_SET(2, &set);)

디스크립터2관찰대상에서 제외 (FD_CLR(2, &set);)

 

fd_set변수에 select 함수에 전달할 디스크립터의 정보를 묶는다.

fd_set변수의 컨트롤

 

관찰의 대상이 되는 디스크립터의 수는 maxfd이며, 번째, 번째, 번째 인자를 통해서 전달된 관찰의 대상 중에서 각각 입력, 출력, 또는 오류가 발생했을select 함수는 반환한다. , timeout지정을 통해서 무조건 반환이 되는 시간을 결정할있다

 

select 함수 호출 이후에는 변화가 발생한(입력 받은 데이터가 존재하거나 출력이 가능한 상황 ), 소켓의 디스크립터만 1설정되어 있고, 나머지는 모두 0으로 초기화 된다.

 

서버소켓의 생성과 관찰 대상의 등록.

 

검색의대상지정

select 함수호출후argument 값이바뀜, readstemps사후select 함수호출.!

select 함수호출후에는타임아웃발생식전시간이담기므로select 함수호출전에매번초기화

데이터입력여부검사

실행하고나서5초후타임아웃발생

파일디스크립터0변화관찰

수신된데이터가있으므로읽는다!

 

연결요청과 일반적인 데이터 전송의 차이점은 전송되는 이터의 종류있다. 따라서 연결요청도 데이터의 수신으구분되어서 select 함수호출결과를 통해서 확인이 가능하다. 따라서 리스닝 소켓도 관찰의 대상에 포함시켜야 한다.

 

FD_ZERO(&reads);

FD_SET(serv_sock, &reads); 

fd_max = serv_sock; 

 

서버소켓(리스닝소켓)을 통한 연결 요청도 일종의 데이터 수신이기 때문에 관찰의 상에 포함시킨다. 

 

cpy_reads = reads; 

timeout.tv_sec = 5;

timeout.tv_usec = 5000; 

 

select 함수를 호출할 때마다 타임아웃을 명시해야 한다.

// select (maxfd, fd_set* readset, fd_set*writeset, fd_set* exceptset, const struct timeeval * timeout); 

 

if((fd_num = select(fd_max+1, &cpy_reads, 0, 0, &timeout)) == -1) break;

if(fd_num == 0) continue; 

 

수신된 데이터가 있는가에 대해서만 관찰하는 select 함수의호출문이다.

select 함수를 호출하고 있다. 호출된 select 함수가 반환을 하면, 반환의 이유를 찰하게 되지만, 타임아웃에 의한 반환이라면, 다시 select 함수를 호출하기 위해서 continue문을 실행해야 한다.

 

 

수신된 데이터가 serv_sock있다면 연결요청이기 때문에 이에 따른 처리를 진행다. 수신된 데이터가 클라이언트와 연결된 켓에 있다면, 이에 따른 에코처리를 진행한다. select 함수의 특성상 이벤트가 발생하면, 이벤트가 발생한 대상을 찾기 위해서 복문을 구성해야 한다. 그리고 이것이 select 함수의 단점으로 지적된다.


select 기반의IO 멀티플렉싱이느린이유

select 함수의 단점

select 함수는 운영체제의 커널에 의해서 완성되는 기능이 아닌, 순수하게 응용프로그램 함수에 의해 완성되는 기능이다. 따라서 select 함수의 호출을 통해서 전달된 정보는 운영체제에 등록되 않는 것이며, 그래서 select 함수를 호출할 때마다매번 관련 정보를 운영체제에게 전달해야 한다. 그리고 것이 select 함수가 지니는 단점의 가장원인이다

 

단점의해결책!

쉽게말해서 select 함수의 단점 극복을 위해서는 운영체제 레벨에서 멀티플렉싱 기능을 지원 한다는 뜻이다. 그리고 리눅스의 epoll, 윈도우의 IOCP 그러한 예에해당한다, 

 

select 이거필요없는것인가? 아니다. 장점이있다

운영체제 레벨이 아닌, 함수 레벨에서 완성되는 기능이다 보니, 호환성이 상대적으 좋다. , 리눅스의 epoll기반 서버를 윈도우의 IOCP 기반으로 변경하는 것은 일이   있는데, 리눅스의 select 기반 서버를 윈도우의 select 기반 서버로 변경하는 것은 매우 간단하다. 절대우위를 점하는 서버의 모델은없다! 따라서 상황에 맞게 적절한 모델을 선택  있어야 한다. 


epoll이해와활용

selectepoll 차이점

( select ) 소켓 24개중 2소켓에서 읽을 데이터가 있다고 가정. select에서는 24개를 전부 검사해야 . 실제로는 2개만 관련이 있음.

( epoll ) epoll(event + poll)에서는 관심있는 소켓들만 이벤트풀에 등록. 만일풀에 있는 소켓에 데이터 변화가 생기면 이벤트발생. 이벤트받은 프로그램은 풀에서 이벤트가 발생한 목록가져올있다. 검사대상을 줄인다. 

 

epoll 방식의장점

상태변화 관찰에 방법을 제공한다. 그리고 커널에서 상태 정보를 유지 하기 때문에 관찰대상의 정보를 매번 전달하지 않아도 된다.

위의 장점은 다른 운영체제에서 제공하는 모든 멀티플렉싱 서버의 장점이기도하다. 소켓 상태 정보를 커널에서 관리

 

epoll구현에필요한함수와구조체

함수 호출통해서 epoll기능완성된다. epoll_event 구조체어떻게 사용되는지 이해하면, epoll이해하는 셈이 된다. 구조체는 소켓 디스크립터의 등록 이벤트 발생의 확인사용되는 구조체이다. 

 

 

epoll_data

epoll_data 안의 ptr 또는 fd이용해서 이벤트가 발생 했을 부가 정보까지 함께 넘길 있다.

아래 그림은 파일(소켓) 지정번호, 유저이름, 별명을 위한 uinfo 구조체만들고 메모리에 정보를 저장해서 파일 저장 번호가 가리킨 상태보여준다. 만일 6파일에 이벤트가 발생하면 uinfo 정보를 읽어온.

 

epoll_create

운영체제가 관리하는, epoll 인스턴스라 불리는 파일 디스크립터의 저장소를생성! 소멸close 함수호출을 통한 종료의 과정이 필요하다. 위의 함수 호출을 통해서 생성된 epll 인스턴스에 관찰대상을 저장 삭제하는 함수가 epoll_ctl, epoll 인스턴스에 등록된 파일디스크립터를 대상으로 이벤트의 발생유무를 확인하는함수가 epoll_wait이다.

 

epoll_ctl

번째 전달인자에 따라 등록, 삭제 변경이뤄진다.

epoll_ctl(A, EPOLL_CLT_ADD, B, C); 

epoll 인스턴스 A, 파일디스크립터 B등록하되, C통해 전달된 이벤트의 관찰목적으등록을 진행한다.

epoll_ctl(A, EPOLL_CLT_DEL, B, NULL); 

epoll 인스턴스 A에서 파일 디스크립터 B삭제한다

 

epoll_ctl  함수 기반의 디스크립터 등록

epoll_event 구조체는 상태변화가 발생파일 디스크립터를 묶는 용도, 리고 epoll 인스턴스에 파일 디스크립등록이벤트의 유형 등록에 사용된다. 

 

event.events = EPOLLIN; // 수신할 데이터가 존재하는 상황, 이벤트 유형 등록 

event.data.fd = sockfd; // 파일 디스크립터 등록 

epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event); 

// epoll 인스턴스 epfd, 파일 디스크립터 sockfd등록하되, &event 통해 전달된 이벤트(EPOLLIN) 관찰을 목적으로 등록을 진행한다비트 OR 연산을 이상을 함께 등록할 있다.

 

epoll_wait

epoll_wait 함수 반환 , 이벤트 발생한 파일 디스크립터의 수가 되고, 번째 인자로 전달된 소의 메모리공간에 이벤트 발생한 파일디스크립터 별도로 묶인다. epoll_wait 함수의 번째 인자를 통해서 이벤트 발생한 디스크립터가 별도로 묶이므로, 전체파일 디스크립터 대상의 반복문은 불필요하다.

epoll_wait(epfd, ep_evenets, EPOLL_SIZE, -1); 

 

epoll 기반의 에코서버 

리스닝소켓의등록과연결요청의대기

epoll 서버의기본모델이다. 리스닝소켓으로전달되는연결요청도수신데이터의일종이므로리스닝소켓epoll 인스턴스에등록하되, EPOLLIN대상으로등록한다

epll_wait 함수호출이후의반복문

연결요청의경우,수락디스크립터등록의과정을거친다

종료요청의경우, 디스크립터해제의과정을친다

메시지수신의경우에코처리한다

 


소켓입출력모델비교

select 특징

등록된file descriptor하나하나체크를해야하고커널과유저공간사이에여러번의데이복사가있음. 관리하는file descriptor수가증가하면성능이떨어진다

관리file descriptor 수에제한이있음.

사용쉽고지원OS많아이식성좋음

select( ) 함수호출전에매번소켓셋을설정해야하고,

select( ) 함수호출후에는매번소켓셋이변경되므로응용프로그램이관리해야부분이많음(성능이떨어짐

 

epoll 특징

SelectPoll 모델과달리{소켓+부가정보}응용프로그램대신커널이직접관리.

유저모드와커널모드간의전환이그만큼적다는뜻이므로성능향상에이바지관리할소켓의개수가많아졌을내부구현의특성상SelectPoll 모델보다성능이우수

select 또는Poll 모델과달리이식성이좋지않음

 

멀티쓰레드구현예제

데이터처리에시간이많이걸리는서비스의경우epoll방식으로만구현하는한계가있슴

아래그림에서보면,데이터읽기까지는epoll사용, 데이터처리데이터쓰기는멀티쓰레드를이용하여구현

728x90