[게임 서버] 3.8 epoll

게시:     수정

카테고리:

태그:

📦 3. 소켓 프로그래밍

👉🏻 항목 8: epoll

🔍 epoll이란?

정의:

  • epoll은 소켓이 I/O 가능 상태가 되면 감지하여 사용자에게 어떤 소켓이 I/O 가능 상태인지 알려준다

💻 epoll 기본 사용법

epoll = new epoll(); // 1

foreach(s in sockets) {
	epoll.add(s, GetUserPtr(s)); // 2
}

events = epoll.wait(100ms); // 3

foreach(event in events) { // 4
	s = event.socket; // 5
	userPtr = event.UserPtr;

	type = event.type; // 송신 or 수신
	if(type == ReceiveEvent) {
		(result, data) = s.recv();
		if(data.length > 0) {
			Proceess(userPtr, s, data);
		}
	}
}

동작 과정:

  • 1번: epoll 객체 생성
  • 2번: epoll에 여러 소켓 추가
    • 각 소켓의 I/O 가능 이벤트 감지 가능
    • 각 소켓의 소켓 소유자 객체 등 원하는 값 삽입 가능
  • 3번: epoll에서 이벤트들을 꺼내오는 함수 wait() 호출
    • 원하는 시간(100ms)까지 블로킹하고, 이전에 이벤트가 생기면 즉시 리턴
  • 4번: 각 이벤트들의 소켓 객체와 사용자 정의 값 가져오기
  • 5번: 원하는 처리 진행

⚠️ 레벨 트리거의 문제점

문제 상황:

  • 실행해보면 소켓의 송신 버퍼가 빈 공간을 유지하는 시간이 짧다
  • 즉, 대부분의 경우는 송신 가능이다
  • 필요 이상의 루프를 돌기에 불필요한 CPU 연산 낭비가 일어난다

⚡ 엣지 트리거 (Edge Trigger)

레벨 트리거 vs 엣지 트리거:

  • 레벨 트리거: I/O 가능 상태(1)를 계속 감지
  • 엣지 트리거: 변화가 있음(0→1, 1→0)을 감지

장점:

  • 이를 사용하면 I/O 가능으로 바뀔 때만 꺼낼 수 있다

🚨 엣지 트리거 사용 시 주의사항

문제 상황:

  1. 소켓에 데이터그램이 2개가 생기고, 엣지 트리거(0→1)가 발생한다
  2. 소켓에서 데이터그램을 꺼내고, 남은 데이터그램은 1개가 된다
  3. 레벨이 1에서 내려오지 않아 고장난다

해결법:

  1. I/O 호출을 would block이 발생할 때까지 반복해야 한다
  2. 소켓은 논블록으로 설정되어 있어야 한다

✅ 엣지 트리거 올바른 구현

...
foreach(event in events) {
	s = event.socket;
	userPtr = event.UserPtr;

	type = event.type; // 송신 or 수신
	if(type == ReceiveEvent) {
		while(true) { // 엣지 트리거(0->1) 활성화 시, 반복
			(result, data) = s.recv();
			if(data.length > 0) {
				Proceess(userPtr, s, data);
			}

			// 이제 소켓에서 모든 데이터그램을 꺼낸다.
			if(result == EWOULDBLOCK) break;
		}
	}
}

핵심:

  • would block이 발생할 때까지 계속 데이터를 꺼내야 한다
  • 이를 통해 소켓 버퍼를 완전히 비운다

🔌 connect()/accept()의 I/O 가능 이벤트

...
foreach(event in events) {
	s = event.socket;
	userPtr = event.UserPtr;

	type = event.type; // 송신 or 수신
	if(type == ReceiveEvent) {
		if(s 리스닝 소켓이면)
			s2 = s.accept();
		else
			s.recv();
	}
}

처리 방법:

  • 리스닝 소켓인 경우 accept() 호출
  • 일반 소켓인 경우 recv() 호출

🧐 정리

구분 레벨 트리거 엣지 트리거
감지 방식 I/O 가능 상태 유지 감지 I/O 가능 상태 변화 감지
이벤트 발생 상태가 1이면 계속 발생 0→1 또는 1→0 변화 시만 발생
CPU 사용 높음 (불필요한 반복) 낮음 (변화 시만 처리)
구현 복잡도 간단 복잡 (would block까지 반복 필요)
소켓 설정 블로킹/논블록 모두 가능 논블록 필수

핵심 포인트:

  • epoll은 여러 소켓의 I/O 이벤트를 효율적으로 감지하는 메커니즘이다
  • 레벨 트리거는 구현이 간단하지만 불필요한 CPU 낭비가 발생한다
  • 엣지 트리거는 효율적이지만 would block까지 반복 처리해야 한다
  • 엣지 트리거 사용 시 반드시 논블록 소켓으로 설정해야 한다
  • accept()recv() 이벤트를 구분하여 처리해야 한다

GameServer 카테고리 내 다른 글 보러가기

댓글남기기