P2P 통신
Last updated
Last updated
클라이언트 간 통신 또는 peer-to-peer 네트워킹(이하 P2P 통신)은 서버를 경유하지 않고 클라이언트 호스트끼리 직접 통신을 하는 것을 일컫습니다.
이 기능은 다음과 같은 상황에서 유용하게 사용됩니다.
서버를 경유해서 통신하기엔 데이터량이 너무 많은 경우
클라이언트끼리 지리적으로 가깝지만 서버가 너무 멀리 있는 경우
서버를 경유하지 않고 클라이언트끼리 직접 네트워킹해서 더 적은 레이턴시를 원하는 경우
Layer 간 이동 동기화를 할 때 P2P 기능을 사용하여 서버의 트래픽을 줄일 수 있습니다. 하지만 반대로 P2P Connection의 수가 많아지면 클라이언트의 트래픽이 과도해 질 수 있고 항상 해킹 위험이 있기 때문에 공격 판정 여부 같은 중요한 데이터는 서버에서도 확인해 주어야 합니다.
ProudNet에서는 해킹에 대한 안정성을 높이기 위하여 P2P의 그룹 생성과 해제 등의 모든 것을 서버에서 관리하고 있습니다.
P2P 연결을 위해서는 먼저 서버에서 클라이언트 간 P2P 그룹을 맺어줘야 합니다. 클라이언트는 자신과 같은 P2P 그룹에 속한 클라이언트와만 P2P 통신이 가능합니다.
클라이언트 간 P2P 그룹을 서버에서 맺어주면 클라이언트끼리는 일단 서버를 통해 P2P relay 통신을 하게 됩니다. 그 동안에 클라이언트 간 P2P 홀 펀칭을 백그라운드로 진행합니다. 만약 P2P 홀 펀칭이 성공하게 되면 그때부터 클라이언트 간 통신은 서버를 경유하지 않고 직접 이루어지게 됩니다. 이를 先 홀 펀칭, 後 릴레이라고 부릅니다. 이러한 특징으로 ProudNet에서는 P2P 그룹을 맺거나 변경한 즉시 클라이언트 간 메시지 송수신이 가능하며 ProudNet 응용 프로그램은 게임 방 시작 시 대기 시간을 요구하지 않습니다. 또한 MMORPG 게임에서 가시 영역의 캐릭터끼리 P2P를 이용한 위치 동기화를 위해 잦은 P2P 연결 및 연결 해제도 안정적으로 수행합니다.
P2P 그룹을 맺자마자 클라이언트 간 통신을 시작하면 서버에서 수 초 동안 서버 측 통신량이 일시적으로 증가하게 됩니다.
홀 펀칭된 클라이언트끼리의 P2P 통신은 UDP와 ProudNet 자체 개발된 Reliable UDP로 이뤄지지만, 홀 펀칭이 성공하기 전까지는 UDP 또는 TCP를 통해 P2P 릴레이를 하게 됩니다. 클라이언트에서 P2P 통신에 사용하는 UDP port는 서버와 연결할 때 사용하는 UDP port와 동일합니다.
일반적으로 P2P 통신을 하는 경우에 비해 relay 통신을 하는 경우가 2배 이상 레이턴시가 큰데, 특히 서버가 거리 상 멀리 있을수록 그 격차는 더욱 커지게 됩니다.
ProudNet에서 다른 클라이언트와 P2P 통신을 하려면 우선 서버에서 P2P 그룹을 개설해야 합니다. 서버에서 P2P 그룹을 Proud.CNetServer.CreateP2PGroup으로 개설하면, 클라이언트에서는 P2P 그룹의 멤버인 클라이언트들의 HostID에 대한 이벤트 Proud.INetClientEvent.OnP2PMemberJoin을 받게 됩니다. 클라이언트에서 이를 받아 처리한 후 서버에서는 Proud.INetServerEvent.OnP2PGroupJoinMemberAckComplete를 받게 됩니다.
서버에서 P2P 그룹의 변화를 클라이언트들이 모두 감지한 후에 다른 뭔가를 처리하고자 할 때 이 이벤트가 효과적입니다.
1. 서버에서 CreateP2PGroup 함수 호출을 통해 P2P그룹을 만듭니다. 2. 클라이언트는 INetClientEvent::OnP2PMemberJoin을 통하여 P2P그룹이 생성되었음을 콜백받게 됩니다. 3. OnP2PMemberJoin 함수를 통하여 그룹에 들어온 클라이언트들과 Member의 HostID값을 받습니다.
게임 중 시야 그룹 처리 및 채팅
기능 | 콜백 | C++ 함수 | C# 함수 |
---|---|---|---|
함수 | 설명 |
---|---|
P2P 그룹에 새로운 member 추가
서버
CNetServer::JoinP2PGroup
Nettention.Proud.NetServer.JoinP2PGroup
클라이언트
INetClientEvent::OnP2PMemberJoin
Nettention.Proud.NetClient.P2PMemberJoinHandler
P2P 그룹에 새로운 member 제거
서버
CNetServer::LeaveP2PGroup
Nettention.Proud.NetServer.LeaveP2PGroup
클라이언트
INetClientEvent::OnP2PMemberLeave
Nettention.Proud.NetClient.P2PMemberLeaveHandler
P2P 그룹 제거
서버
CNetServer::DestroyP2PGroup
Nettention.Proud.NetServer.DestroyP2PGroup
클라이언트
INetClientEvent::LeaveP2PGroup
Nettention.Proud.NetClient.LeaveP2PGroup
CreateP2PGroup
Client 접속, 채팅 그룹 생성
DestroyP2PGroup
Client 접속 해제, 채팅 그룹이 제거될 때
JoinP2PGroup
다른 유저가 시야 안에 들어올 때, 새 유저가 방에 들어올 때
LeaveP2PGroup
다른 유저가 시야 밖으로 나갈 때, 기존 유저가 방에서 나갈 때