P2P Tips
P2P 프로그래밍에 있어서 주의해야 할 항목들을 정리해 보았다. 입문자에게 많은 도움이 되었으면 한다. (참고로 본인은 직접 P2P를 개발하기보단 동료가 삽질하는 걸 지켜본 쪽이라서, 정확하지 않은 내용이 있을 수 있음을 먼저 밝힌다)
분석 및 검토
게임성 분석
만들고자 하는 게임의 다양한 속성들에 대한 분석이 최우선 단계이다. 다음 질문에 자신의 게임이 어떤 쪽인지를 잘 따져보기 바란다.
- 최대접속자는 얼마인가? (4-8, 16-32, 64-256, Massive)
- 카운터 스트라이크처럼 사용자들에게 핑이 빠른 서버를 선택할 수 있도록 할 것인가?
- NPC 또는 몹이 존재하는가? 만약 그렇다면 누가 그들을 움직이게 할 것인가?
- 승패 또는 타격 판정, 이동에 대한 검증은 누가 할 것인가?
- dedicated server 를 지원할 것인가? 또는 클라이언트 중에서 UDP 서버를 선택할 것인가?
토폴로지의 선택
어떤 토폴로지를 선택하느냐에 따라서 최대 대역폭, 최대 접속자가 결정되므로, 위에서 조사한 결과에 따라서 적합한 토폴로지를 선택해야 한다. 아래의 문서를 참고하기 바란다.
see also : 네트워크 액션 게임의 분류
UDP 라이브러리의 선택
토폴로지를 선택했다면 이제 UDP 라이브러리를 선택할 단계이다.
단지 위치 정보만을 보내는 게 아닌 이상, 순수 UDP 만으로 네트워크 게임을 개발하기란 쉽지 않다. 결국은 reliable UDP 를 지원하는 외부 라이브러리를 사용하거나 직접 구현하게 될텐데, 직접 구현하는 것은 시간이 많거나 자신이 천재가 아닌 이상 그다지 좋은 선택은 아니다. 반면 어떤 라이브러리를 선택해도 깊은 이해 없이는 잘 사용하기가 힘든 것이 사실이다.
가능하면 Unreal, Source Engine 등 네트워크 모듈이 포함된 게임 엔진을 구매하는 것을 권장하며, 그럴 수 없다면 충분한 검토 기간 하에 RakNet, OpenTNL, udt, enet 중에서 하나를 선택하기 바란다.
디자인 및 구현, 테스트
네트워크 모듈의 통합
많은 UDP 라이브러리들은 보다 빠른 반응성을 위해 자체적으로 쓰레드를 사용한다. 그러나 dedicated server 가 아닌 이상, 서버쪽은 무작정 쓰레드를 남발해서는 곤란하다. 하나의 서버가 여러 개의 게임을 동시 처리해야 할 경우가 많으므로, 이럴 때에는 소스를 수정해야 할 수 있다.
- polling vs. event-driven
- single thread vs. multithread
이때 폴링 방식의 클라이언트는 로딩 혹은 렌더링으로 인해 네트워크 업데이트를 방해하는 일이 없도록 주의해야 한다.
NAT와 홀펀칭
- 하드웨어의 구비
- 하드웨어가 없는 상태에서의 NAT 프로그래밍은 장님 코끼리 다리 만지기와 같다.
- SNAT
- SNAT-SNAT 간에는 홀펀칭이 통하지 않는다는 사실만 기억하면 된다. 중국이 아닌 이상 SNAT를 만나기란 쉽지 않다. 정 귀찮다면 C/S구조로 가는 것도 나쁘지 않다. GPGStudy 포럼을 잘 검색하면 어떤 라우터가 SNAT인지를 찾을 수 있다.
- N+1
- 어떤 NAT는 새로운 매핑을 위해 포트 번호를 점차 증가시키기도 한다. 그러나 라우터 제조 업체마다 다르므로 일반적으로는 알 수 없다고 봐야 한다. Timeout 30-40초마다 패킷을 밖으로 쏘지 않을 경우 매핑을 삭제하는 공유기가 존재한다.
- 패킷 릴레이
- 직접적인 통신이 되지 않는 peer 에게 패킷을 보낼 수 있는 유일한 방법이다. 문제는 릴레이는 핑이 2배 느려지는 것이 보통이므로 데드 레커닝 및 보간 기능으로 잘 극복해야 한다. 릴레이가 끊기는 경우 실시간으로 다른 루트를 찾아주면 금상첨화.
- 사설 네트워크
- 같은 네트워크에 있는 사용자들 끼리는 굳이 public 주소로 접속할 필요는 없다. 상대방의 (public,private) 모두로 핑을 쏜 다음, 응답이 오면 그 중 빠른 넘을 실제 주소로 선택하라. 이때 둘 다 될 경우라면 대체로 private를 사용하는 편이 좋다. 물론 본인 확인은 필수. 방화벽 내부에 있는 사람들끼리 플레이할 경우 public 으로 통신하면 괴로워진다.
- 다단계 NAT
- 중국은 다단계 NAT로 악명이 높다. 최소한 2단계로 NAT를 배치한 후 각 노드마다 클라이언트를 두고 내부/외부와 통신이 잘 되는지를 확인할 것. 그렇게 열심히 테스트해도 안되는 환경이 분명 존재하므로, 처음부터 릴레이를 기본 기능으로 포함시킬 것.
- 사용자 서버
- 네트워크 비용을 줄이려면 특정 클라이언트가 서버 역할을 하도록 하라. 단 Drop-out시 게임을 중단하고 새 서버를 찾는 기능을 구현해야 한다. 물론 보안 문제는 책임질 수 없다;;
대역폭 관리
- 모뎀 지원
- 해외에는 아직도 모뎀을 많이 사용하고 있다. 따라서 모뎀 유저가 방에 들어올 경우 최대 접속자를 줄이든가 대역폭에 맞게 데이터를 실시간 관리하는 기능이 필요하다.
- MTU
- 게임에서의 최대 패킷 크기를 항상 알고 있을 것. 특히 리스트 방식으로 전송되는 데이터들(방 목록, 사람 목록, 게임 목록)을 유의할 것.
- 순간 대역폭
- 체크 어떤 공유기(D-Link)는 순간 대역폭을 초과할 경우 reset 되기도 한다.
공유기, 방화벽, 포트 포워딩
- (D)DOS 공격
- 어떤 공유기는 외부로부터 갑자기 연결이 많이 들어올 경우 DOS 혹은 DDOS 로 간주해서 연결을 차단하기도 한다.
- XP 방화벽
- Windows XP의 방화벽에 자동 등록하기는 필수. 단 사용자에게 허가를 받지 않고 몰래 방화벽을 끌 경우 해외에서는 고소당할 수 있다.
- 백신 호환성 체크
- 일부 백신들은 정상적인 어플리케이션도 바이러스나 웜으로 간주하기도 한다. 따라서 유명 백신들을 설치한 상태에서 툴과의 호환성을 체크한 후 문제가 있다면 매뉴얼을 홈페이지에 등록해야 한다.
- 포트 포워딩
- portforward.com이나 WOW처럼 공유기에서 포트포워딩을 하는 방법을 홈페이지에 기술할 것. 가능하면 클라이언트에 네트워크 진단 도구를 탑재하거나, 웹 기반 진단 페이지를 만들기를 권장한다.
- 주의 깊은 포트의 선택
- 해외의 일부 회선 업체는 자신들의 자체 서비스(VoIP)를 위해 특정 UDP 포트를 임의로 막기도 한다. 가능한한 다른 게임 및 어플리케이션과 충돌하지 않는 포트를 선택할 것.
- 서버 방화벽
- 네트워크 관리자에게 사용하는 포트에 대한 문서를 넘기고 수시로 업데이트 해줄 것. (특히 해외 서비스일 경우는 필수) 허용된 포트의 끝언저리에서 실수로 인한 문제가 종종 생기곤 한다.
기타
- 공유기의 타입 찾기 : STUN
- Drop-In : 게임 도중 새로운 접속자가 들어올 때
- 연결 끊김 감지 : 게임 도중 연결이 끊길 경우 얼마나 빨리 감지할 수 있을까?
- 데이터 복제, 보안, 통계 수집