일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 백준
- 신경망 학습
- 경사하강법
- Mac
- 1002
- 재귀
- 파이썬
- end to end
- 개발환경
- 설정
- 9020
- 기계학습
- N-Queen
- 실버
- 그리디 알고리즘
- 파이싼
- 밑바닥부터 시작하는 딥러닝
- pyenv
- streamlit
- 4948
- 백트래킹
- BOJ
- Python
- 손실함수
- 가상환경
- n과 m
- 15649
- 1101
- Today
- Total
파이톨치
[socket programming] IO multiplexing 본문
멀티프로세스 서버의 단점과 대안
멀티프로세스 서버의 단점
프로세스의 빈번한 생성은 성능의 저하로 이어진다.
멀티 프로세스의 흐름을 고려해서 구현해야 하기 때문에 구현이 쉽지 않다.
프로세스간 통신이 필요한 상황에서는 서버의 구현이 더 복잡해진다.
멀티프로세스 서버의 대안
하나의 프로세스가 다수의 클라이언트에게 서비스를 할 수 있도 록한다.
이를 위해서는 하나의 프로세스가 여러 개의 소켓을 핸들링 할 수 있는 방법이 존재해야 한다. 바로 이것이 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 값이바뀜, reads를temps에복사후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의이해와활용
select와 epoll 차이점
( 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 특징
Select나Poll 모델과달리{소켓+부가정보}를응용프로그램대신커널이직접관리.
유저모드와커널모드간의전환이그만큼적다는뜻이므로성능향상에이바지•관리할소켓의개수가많아졌을때내부구현의특성상Select나Poll 모델보다성능이우수
select 또는Poll 모델과달리이식성이좋지않음
멀티쓰레드구현예제
데이터처리에시간이많이걸리는서비스의경우epoll방식으로만구현하는건한계가있슴
아래그림에서보면,데이터읽기까지는epoll을사용, 데이터처리및데이터쓰기는멀티쓰레드를이용하여구현
'대학수업 > socket programming' 카테고리의 다른 글
[socket programming] IoT Datalink layer protocol (0) | 2024.04.20 |
---|---|
[socket programming] 멀티 쓰레드 기반의 서버 구현 (1) | 2024.04.20 |
[socket programming] 멀티 프로세스 기반 다중 서버 (0) | 2024.04.19 |
[socket programming] Socket Options (2) | 2024.04.19 |
[socket programming] UDP socket program (1) | 2024.04.19 |