어떻게 C 로 웹 서버 의 I/O 다 중 재 활용 을 씁 니까?
I/O 모델
socket 프로 그래 밍 을 접 한 학생 들 은 모두 I/O 모델 의 개념 을 알 아야 한다.Liux 에는 I/O,비 차단 I/O,I/O 다 중 재 활용,신호 구동 I/O 와 비동기 I/O 다섯 가지 모델 이 있다.
다른 모델 의 구체 적 인 개념 은 여기 서 소개 하지 않 고 자신 이 이해 하 는 I/O 다 중 재 활용 만 간단하게 제시 합 니 다.쉽게 말 하면 하나의 프로 세 스 로 여러 개의 socket 을 관리 하 는 것 입 니 다.곧 여러 개의 socket 을 하나의 표 에 넣 을 것 입 니 다.그 중에서 socket 이 조작 할 수 있 을 때 프로 세 스 에 알 리 고 처리 하 는 것 입 니 다.I/O 다 중 재 활용 의 실현 방식 은 select,poll 과 epoll 이 있 습 니 다.
select/poll/epoll
Liux 에서 파일 설명자(file descriptor,하 fd)를 통 해 socket 작업 을 하기 때문에 다음 글 은 모두 fd 작업 입 니 다.
먼저 처음에 실 현 된 select 의 문 제 를 말 합 니 다.
4.567917.select 에서 열 린 fd 의 최대 수량 은 제한 이 있 고 보통 1024 이 며 현재 계산 시스템 의 병발 량 전에 약간 적용 되 지 않 습 니 다
마지막 으로 epoll 은 Linux 2.6 의 커 널 에 출시 되 었 습 니 다.이벤트 체 제 를 사용 하여 모든 fd 에 이 벤트 를 추가 합 니 다.fd 의 이벤트 가 실 행 될 때 리 셋 함수 로 대응 하 는 이 벤트 를 처리 합 니 다.epoll 의 장점 은 다음 과 같 습 니 다.
4.567917.활발 한 fd 에 만 관심 을 가지 고 정확 한 포 지 셔 닝 을 하여 poll 의 시간 효율 O(n)에서 O(1)로 바 꾸 었 다
epoll 소개
epoll 은
epoll_create
int epoll_create(int size);
epoll 인 스 턴 스 를 만 들 고 이 epoll 인 스 턴 스 를 가리 키 는 파일 설명 자 를 되 돌려 줍 니 다.epoll 인 스 턴 스 를 더 이상 사용 하지 않 을 때 close()방법 으로 닫 아야 합 니 다.
최초의 실현 에서 size 는 시스템 이 충분 한 공간 을 분배 할 수 있 도록 열 려 있 는 최대 fd 수로 들 어 옵 니 다.최신 버 전의 커 널 에서 시스템 커 널 동적 할당 메모리 에는 더 이상 이 매개 변수 가 필요 하지 않 습 니 다.그러나 프로그램 이 오래된 커 널 에서 실행 되 는 데 문제 가 있 는 것 을 피하 기 위해 서 는 이 값 이 0 이상 이 어야 합 니 다.
epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epfd 는 epollcreate 에서 돌아 오 는 파일 설명자
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* epoll */
epoll_data_t data; /* */
};
epoll_waitint epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); epoll 이벤트 감청:
4.567917.이 벤트 는 epoll 이벤트 배열 이 고 epoll 이벤트 의 구조 에 대해 이미 소개 되 었 습 니 다4.567917.maxevents 는 감청 으로 얻 은 최대 사건 수 입 니 다
epoll 에서ctl 의 이벤트 매개 변수 에서 이벤트 이 벤트 는 다음 과 같은 옵션 이 있 습 니 다.
EPOLLIN(읽 기 가능),EPOLLOUT(쓰기 가능),EPOLLRdhup(연결 종료),EPOLLPRI(긴급 데이터 읽 기 가능),그 밖 에 EPOLLERR(오류),EPOLLHUP(연결 끊 기)사건 은 epoll 기본 값 으로 계속 감청 됩 니 다.
이벤트 설정 외 에 감청 행위 도 설정 할 수 있 습 니 다.
코드 구현
전체 처리 논리
epoll 을 사용 할 때 서버 수리 클 라 이언 트 요청 논 리 는 다음 과 같 습 니 다.
1.서버 socket 을 만 들 고 서버 socket 읽 기 이 벤트 를 등록 합 니 다.
2.클 라 이언 트 가 서버 에 연결 하여 서버 socket 을 읽 을 수 있 도록 촉발 하고 서버 가 클 라 이언 트 socket 을 만 들 고 클 라 이언 트 socket 읽 기 이 벤트 를 등록 합 니 다.
3.클 라 이언 트 가 데 이 터 를 보 내 고 클 라 이언 트 socket 을 읽 을 수 있 도록 촉발 합 니 다.서버 가 클 라 이언 트 정 보 를 읽 고 응답 을 socket 에 기록 합 니 다.
4.클 라 이언 트 가 연결 을 닫 고 클 라 이언 트 socket 을 읽 을 수 있 도록 촉발 합 니 다.서버 가 클 라 이언 트 정 보 를 읽 는 것 이 비어 있 고 클 라 이언 트 socket 읽 기 이 벤트 를 취소 합 니 다.
erver_fd = server_start();
epoll_fd = epoll_create(FD_SIZE);
epoll_register(epoll_fd, server_fd, EPOLLIN|EPOLLET);// socketEPOLL ET
while (1) {
event_num = epoll_wait(epoll_fd, events, MAX_EVENTS, 0);
for (i = 0; i < event_num; i++) {
fd = events[i].data.fd;
// socket ,
if ((fd == server_fd) && (events[i].events == EPOLLIN)){
accept_client(server_fd, epoll_fd);
// socket , ,
} else if (events[i].events == EPOLLIN){
deal_client(fd, epoll_fd);
} else if (events[i].events == EPOLLOUT)
// todo ,
continue;
}
}
주의해 야 할 것 은 클 라 이언 트 socket 은 읽 을 수 있 는 후에 도 바로 쓸 수 있 습 니 다.저 는 요청 을 직접 읽 은 다음 에 응답 정 보 를 write 에 넣 고 데 이 터 를 읽 을 때 버퍼 가 가득 찬 문 제 를 고려 하지 않 았 습 니 다.여기 서 제시 한 해결 방안 은 다음 과 같다.
1.클 라 이언 트 socket 과 buffer 의 해시 표를 설정 합 니 다.
2.정보 버퍼 가 가득 찼 을 때 recv 는 EAGIN 오 류 를 되 돌려 줍 니 다.이 때 데 이 터 를 buffer 에 넣 고 응답 하지 않 습 니 다.
3.후속 읽 기 이벤트 에서 데이터 끝 을 읽 은 후 socket 을 등록 하여 이 벤트 를 쓸 수 있 습 니 다.
4.쓰기 가능 한 이 벤트 를 처리 할 때 buffer 의 모든 요청 내용 을 읽 고 처리 가 끝 난 후에 클 라 이언 트 에 응답 합 니 다.
5.마지막 으로 socket 쓰기 이 벤트 를 취소 합 니 다.
epoll ET(edge trigger)모드 설정
앞에서 말 했 듯 이 ET 모델 은 epoll 의 효율 적 인 모델 로 사건 은 한 번 만 알려 주지 만 잘 처리 하면 높 은 병행 에 더욱 적 용 될 것 이다.그것 은 socket 이 비 차단 모드 에서 만 사용 할 수 있 습 니 다.여기에서 우 리 는 그것 을 실현 합 니 다.
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
// socket , " "
flags = fcntl(sock_fd, F_GETFL, 0);
fcntl(sock_fd, F_SETFL, flags|O_NONBLOCK);
.....
// socket EPOLL ET
epoll_register(epoll_fd, server_fd, EPOLLIN|EPOLLET);
저 는 사건 을 처리 한 후에 클 라 이언 트 연결 요청 을 사용 하여 테스트 를 했 습 니 다.ET 모드 에서 사건 이 한 번 만 발생 하 는 현상 을 명확 하 게 설 명 했 습 니 다.앞 뒤 대비 도 는 다음 과 같 습 니 다.작은 매듭
Mac OS X 운영 체제 의 일부 부분 은 FreeBSD 를 바탕 으로 하 는 것 입 니 다.FreeBSD 는 지원 하지 않 습 니 다.MAC 도 지원 하지 않 습 니 다.(비슷 한 kquue 가 있 을 뿐)개발 기 에 가서 개 발 했 습 니 다.가장 기본 적 인 C learner 로 서 printf()와 fflush()두 함수 로 디 버 깅 을 했 습 니 다.오래 하지 않 아 드디어 완 성 했 습 니 다.C 선배 님 께 서 디 버 깅 방식 을 추천 해 주 셨 으 면 좋 겠 습 니 다.
이상 은 C 로 웹 서버 의 I/O 다 중 재 활용 에 대한 상세 한 내용 입 니 다.C 로 웹 서버 의 I/O 다 중 재 활용 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 시기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Docker를 사용한 React 및 .NET Core 6.0 샘플 프로젝트 - 1부이 기사에서는 Entity Framework Core Code First 접근 방식을 사용하는 ASP.NET Core 6.0 WEP API의 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업에 대해 설명합니다. 웹 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.