✅ 한 것들
📖 게임 서버 프로그래밍 교과서
3장 소켓 프로그래밍
소켓 비동기 입출력 방식
- 논블로킹 소켓 : 기다리지 않는 소켓
- Overlapped I/O : 한 소켓에서 여러 I/O 요청
- epoll : 소켓 변화 생기면 반환
- IOCP (I/O Completion Port) : 입력 오면 스레드풀이 일함
3.3 블로킹과 소켓 버퍼
send()는 소켓 버퍼 꽉 차지 않는 이상 블로킹 없이 바로 반환
송신 버퍼는 디폴트로 수천 바이트를 담을 수 있다
3.5 수신 버퍼가 가득 차면 발생하는 현상
수신 버퍼 꽉 차면 TCP 데이터 보내는 쪽에선 send() 블로킹됨
보냈는데 여유 공간 없으면 데이터그램 버려짐
TCP는 수신 가능 데이터양이 송신 속도보다 낮으면 알아서 송신량 줄임
UDP는 꽉 차면 그냥 계속 보내고 계속 버려짐
이 때문에 라우터가 패킷을 버려서 주변 네트워킹 두절되기도 함
3.6 논블록 소켓
네트워킹 해야 하는 대상 여럿일 때
네트워킹 대상 개수만큼 스레드 만들기
: 스레드 개수 1000개면 각 스레드 차지하는 호출 스택이 1메가이므로 총 1기가
컨텍스트 스위치도 대량 발생
논블록 소켓
: 논블록 수신으로 소켓들 루프 돌기
TCP일 때 connect()가 논블로킹이라면 0바이트 송신해서 연결 됐는지 안됐는지 확인해야함
서버가 busy waiting 방식으로 사용량 100% 찍으며 기다리면 곤란하니까 select()나 epoll() 사용
3.7 Overlapped I/O 혹은 비동기 I/O
논블록 소켓 장점
- 스레드 블로킹 없으므로 중도 취소 같은 통제 가능
- 스레드 개수가 1개여도 소켓 여러 개 다룰 수 있음
- 스레드 개수 적어서 연산량, 호출 스택 낭비 안됨
논블록 소켓 단점
- 변화 없으면 재시도 호출 낭비 발생 : UDP는 송신 버퍼 크기보다 보낼 데이터가 크면 못 보내고 헛발질만 계속함
- 소켓 입출력 함수 호출 시 입력하는 데이터 블록 복사 연산 발생 : 캐시 미스되면 RAM 액세스 해야될 때도 있음
- send(), receive()는 재시도 호출 API가 일관되지 않다
Overlapped I/O
- 윈도 전용
- Overlapped I/O 함수는 즉시 리턴되지만, 운영체제가 별도로 해당 I/O 진행
- 운영체제는 소켓 함수 인자로 넣었던 데이터 블록과 Overlapped Status 객체를 백그라운드에서 액세스
- 따라서 완료되기 전까지 두 객체 수정/삭제하면 안됨
- Overlapped I/O 전용 송수신 함수 호출하면 운영체제는 데이터 있는 메모리 블록 자체를 송신 버퍼로 사용
Overlapped I/O 장점
- 재시도 호출 낭비 없다
- 데이터 블록 복사 연산 없앤다
3.8 epoll
epoll은 I/O 가능일 때만 루프 돈다. 성능 개선될 것 같지만,
현실에선 대부분 송신 버퍼에 데이터 계속 주어진다.
레벨 트리거 : 소켓이 I/O 가능함
엣지 트리거 : I/O 가능 아니었는데, 가능해졌다
엣지 트리거 쓸 땐 여러 소켓의 데이터 다 꺼내도록 반복