게임 서버 프로그래밍 시 주의사항
- 게임 서버는 TCP를 이용할 경우 클라이언트의 개수만큼 소켓이 있어야 함
- 파일 핸들을 하는 동안 스레드가 대기하는 일이 없어야 함
소켓에 대한 입출력 방식
- 동기 입출력 방식 : 블로킹 소켓(blocking socket)
- 비동기 입출력 방식 : 논블로킹 소켓(non-blocking socket), Overlapped I/O, epoll, I/O Completion Port(IOCP)
블로킹 소켓(blocking socket)
1) 블로킹(blocking)이란?
- 디바이스에서 처리 요청(받은 데이터를 디바이스에 기록 혹은 호출)을 걸어 놓고 응답을 대기하는 함수 호출 시, 스레드에서 발생하는 대기 현상
- 해당 상태에서는 CPU 사용량이 0%이므로 스레드는 waitable state가 됨
- 이 상태동안 파일이나 소켓의 실제 처리는 디바이스에서 이루어짐
2) 송신 버퍼와 수신 버퍼
- 소켓은 송신 버퍼(send buffer)와 수신 버퍼(receive buffer)를 하나씩 가지고 있음
- 송신 버퍼는 일련의 바이트 배열(byte array), 크기는 고정되어 있으나 마음대로 변경할 수 있음
- send()함수가 호출되면 송신 측 소켓의 송신 버퍼에 데이터가 채워지지만 금방 빠져나감
- 송신 버퍼가 꽉 차있을 경우 블로킹이 발생
- 수신 버퍼는 수신할 데이터가 있을 때까지 블로킹 상태
- TCP는 송신자가 초당 보내는 데이터양이 수신자가 초당 수신할 수 있는 데이터양보다 많을 때, 알아서 송신자 측 운영체제가 초당 송신량을 줄임(혼잡 제어)
- UDP는 혼잡 제어가 없기 때문에 같은 상황에서 네트워크가 두절될 수 있는데 이를 혼잡(Congestion)이라 함
논블록 소켓(non-block socket)
- 논블록 소켓은 호출 함수에 대하여 성공, 혹은 would_block 둘 중 하나만 반환함
- would block이 호출되면 아무것도 안함
- TCP에서 0바이트를 송신하면 아무것도 하지 않음, 이를 이용해 TCP 소켓이 어떤 상태인지 확인할 수 있음
- 0바이트 송신 함수가 성공하면 TCP 연결이 되어있다는 의미, ENOTCONN(소켓이 연결되지 않았음)
- select 함수 = 여러 소켓 중 하나라도 송신 버퍼에 빈 공간이 생기거나 수신 버퍼에 뭔가가 들어오면 그 상황을 알려줌, 그것을 알리기 전까지는 블로킹 중이어서 CPU 사용량 폭주를 해결하는 함수
논블록 소켓의 장단점
장점
- 스레드 블로킹이 없으므로 중도 취소 가능
- 스레드 개수가 1개이거나 적어도 소켓 여러개 다룸
- 스레드 개수가 적거나 1개이므로 연산량이 낭비되지 않으며 호출 스택 메모리도 낭비되지 않음
단점
- would block인 경우 재시도 호출 낭비
- 소켓 I/O 함수 호출 때 입력하는 데이터 블록에 대한 복사 연산 발생
- send()나 receive() 함수는 재시도 호출해야 하는 API가 일관되지 않음
Overlapped I/O or 비동기 I/O
- 논블록 소켓에서 발생하는 재시도용 호출 낭비 문제와 소켓 함수에 데이터 블록 복사 부하 문제를 해결
- 코드가 돌고 있는 것과 별개로 백그라운드에서 OS가 데이터에 접근
- 단 소켓 개수에 비례해서 루프가 돌기 때문에 성능에 문제가 발생
- 이를 해결하기 위해 epoll 과 IOCP가 등장
epoll
- epoll은 소켓이 I/O 상태가 되면 이를 사용자에게 알려줌
- 단, 리눅스와 안드로이드에서만 사용 가능
select 방식과 IOCP 방식
1) select 방식
- read, write에서 버퍼가 비었는지 수시로 확인하며 빈 경우 사용
2) IOCP
- 데이터 전송을 요청해두고 다른 일을 수행함
- 수신 측도 데이터가 수신되기 전까지 다른 작업을 수행
- OS가 성능처리를 해주며 일을 분담
'게임 회사 > 서버 프로그래밍' 카테고리의 다른 글
[2] 컴퓨터 네트워크 (0) | 2022.06.01 |
---|---|
[1]스레드와 멀티 스레드 (0) | 2022.05.31 |