네트워크 클라이언트-서버 메시지 교환 및 클럭 동기화 도움말


10

저는 테이블 하키 인 빠른 속도의 물리 게임을하고 있습니다. 두 개의 망치와 하나의 퍽으로. 게임은 iphone / ipad에서 실행되며 GameCenter를 통해 멀티 플레이어 부분을 수행하고 있습니다.

이것이 네트워크 시스템의 작동 방식입니다. 클라이언트는 매치를 시작하고 서버로 설정되며 매치 요청을 수락하는 클라이언트는 클라이언트입니다.

'서버'에는 물리가 실행 중이며 응답이 즉시 이루어지며 클라이언트도 물리가 실행 중이므로 메시지 교환이 원활하게 이루어집니다. 내가 서버로하는 일은 클라이언트에게 내 퍽 속도와 내 위치를 보내고 클라이언트가 서버와 관련된 퍽 속도 / 위치를 조정하여 동기화되도록한다는 것입니다. 그렇지 않으면 물리가 비 동기화되어 나사를 조입니다.

네트워크 대기 시간이 좋으면 100ms 이하의 결과가 꽤 좋습니다. 클라이언트 측에서 부드러운 게임을 할 수 있으며 이상한 행동이 최소화됩니다. 지연이 약 150 ~ 200ms 인 경우 문제가 발생합니다. 이 경우 클라이언트 퍽이 이미 가장자리와 반대 방향을 쳤지 만 서버에서 지연 메시지를 수신하고 약간 뒤로 물러서 공 동작에 이상한 느낌을줍니다.

나는 그것에 대해 몇 가지를 읽었습니다.

탁구 네트워크 예

동기화 예를 클릭하십시오.

시계 동기화 위키 백과

어떻게 해결할 수 있습니까? 내가 가지고있는 가장 좋은 옵션을 읽은 한 타임 스탬프와 함께 서버 / 클라이언트에서 시계 동기화를 수행하여 시계와 관련된 지연 메시지를 얻을 때 무시하고 클라이언트 시뮬레이션을 수행하도록합니다. 일. 당신은 그것에 동의합니까? 그리고 IM을 신뢰할 수없는 데이터 (UDP)로 보내면 지연 된 메시지 또는 메시지가 잘못 나타날 수 있습니다.

이것이 최선의 방법이라면 시계 동기화를 어떻게 구현합니까? 방법에 대한 단계를 읽었지만 이해하지 못했습니다.

그것은 말합니다 :

  1. 클라이언트는 "시간 요청"패킷에 현재 현지 시간을 표시하고 서버로 보냅니다.
  2. 서버가 서버를 수신하면 서버는 서버 시간을 표시하고 반환
  3. 클라이언트가 수신하면 클라이언트는 전송 된 시간에서 현재 시간을 빼고 두 시간으로 나누어 대기 시간을 계산합니다. 서버 시간에서 현재 시간을 빼서 클라이언트-서버 시간 델타를 결정하고 올바른 클럭 델타를 얻기 위해 반 대기 시간을 추가합니다. (지금까지이 algothim은 SNTP와 매우 유사합니다)
  4. 클라이언트는 1 ~ 3 단계를 5 번 이상 반복하여 매번 몇 초씩 일시 중지합니다. 다른 트래픽은 중간에 허용 될 수 있지만 최상의 결과를 얻으려면 최소화해야합니다. 패킷 수신 결과는 가장 낮은 지연 시간에서 가장 높은 지연 시간 순서로 누적되어 정렬됩니다. 중간 지연 시간은이 정렬 된 목록에서 중간 점 샘플을 선택하여 결정됩니다.
  5. 중앙값으로부터 대략 1 표준 편차를 초과하는 모든 샘플은 버리고 나머지 샘플은 산술 평균을 사용하여 평균화됩니다.

이 예제를 따르면 다음과 같이됩니다.

게임이로드되었다고 가정하고 클라이언트 시간은 지금 0이므로 서버에 내 시간이 0임을 보냅니다.

메시지는 서버에 도달하는 데 150ms가 걸리지 만 서버의 시계는 이미 시작되었으며 클라이언트보다 1 초 앞서 있습니다. 서버가 메시지를 받으면 시간은 1.15가되고 그 시간을 클라이언트에게 보냅니다. 지연이 150ms로 일정하다고 가정하자.

이제 클라이언트는 시간 1.15를 수신하고 전송 된 시간에서 현재 시간을 빼고 대기 시간을 계산하기 위해 2로 나눕니다. Wich는 0.3-0 = 0.3 / 2-> 150ms입니다.

클라이언트 시간 : 델타 시간을 결정하기 위해 서버 시간에서 현재 시간을 빼고 올바른 클럭 델타를 얻기 위해 반 지연 시간을 추가합니다.
클라이언트 시간 : 0.3 서버 시간 1.15
0.3-1.15 = .85 + 대기 시간 (.15) = 1

어떻게 동기화 되나요? 내가 무엇을 놓치고 있습니까?

멀티 플레이어와 네트워크 경험이 처음이므로 혼란 스럽습니다.

감사합니다.


좋은 질문. 0.3-1.15를 1.15-0.3으로 수정 하시겠습니까?
Ciaran

답변:


12

게시 된 알고리즘은 정확하지만 예제에서는 서버 패킷이 클라이언트에 도달하는 데 걸리는 시간을 잊어 버렸습니다.

Server time: 1
Client time: 0
Client sends 0 to server

... 150ms to get to server  (ping is 300! not 150ms in this case. Ping is round-trip)

Server time: 1.15
Client time: 0.15
Server receives packet and sends client 1.15

... 150ms to get back to client

Server time: 1.30
Client time: 0.30
Client receives 1.15 from server

보시다시피 클라이언트가 시계를 1.15로 변경하면 서버 뒤에서 0.15가되므로 Ping (일명 왕복 시간 (RTT))을 조정해야합니다. 여러 단계에 걸쳐 수행 된 전체 델타 시간 계산은 다음과 같습니다.

Server Time - Current Time + Ping / 2
= Server Time - Current Time + (Current Time - First Packet Time) / 2
= 1.15 (Perceived, not actual!) - 0.30 + (0.30 - 0.00) / 2
= 1.00

이것은 우리에게 1.00 초의 정확한 델타 시간을줍니다


나는 그것을 얻는다. 그래서 내 클라이언트 시계는 1.00이고 서버는 1.30이다. 서버에서 메시지를 얻은 후에 핑 메시지를 추가하여 늦은 메시지인지 확인해야합니까? 대기 시간이 변경되면 항상 그 계산을 계속해야합니까?
gmemario

클라이언트 시간이 서버 시간과 같도록 델타 시간 1.00 초가 현재 시계에 추가됩니다. 지연 시간은 항상 변경되며 각 패킷에는 약간 다른 RTT가 있습니다. 게임에서와 같이 짧은 시간 내에이 시간 동기화를 한 번만 수행하면 클라이언트는 서버의 시간을 정확히 추측 할 수 있으며 두 시계가 거의 같은 속도로 진행해야합니다. 미래에서 온 것으로 보이는 패킷을받은 경우는 예외입니다. 이 경우 두 가지 해결책이 있습니다. 1) 새로운 시간 동기화를 수행하십시오. 2) 미래의 시계와 일치하도록 시계를 발전 시키십시오
John McDonald

좋아,이 상황을 살펴보면 내가 얻을 수 있는지 확인하십시오. 서버 시간 : 1s 클라이언트 시간 : 0s 150ms 서버에 도달 서버 시간 : 1.15s 클라이언트 시간 : 0.15s 서버는 클라이언트 1.15s 200ms를 클라이언트에 보냅니다. 이제 내 핑은 350ms입니다. 그 맞습니까? 서버 시간 : 1.35 클라이언트 시간 : 0.35 계산 수행 : 1.15-.35 + (0.35-0.00) / 2 이제 내 deltaTime = 0,975 델타 시간 0,975를 .35에 추가하면 다음과 같이됩니다. 1,325 Wich는 일종의 비동기입니다. 맞습니까?
gmemario

@ 길슨, 맞습니다. 두 패킷의 대기 시간이 다르면 (거의 보장됨) 클라이언트의 델타 시간 계산이 완벽하지 않습니다. 클라이언트가 완벽 할 수있는 방법은 없습니다. 질문에 설명 된 알고리즘에서 델타 시간은 여러 번 계산 되었으며이 결과를 선택하고 평균화하는 방법이있었습니다. 많은 시간 동기화 방법은 이와 같은 작업을 수행하지만 일반적으로 증권 거래소와 같이 비즈니스에 중요하고 오래 실행되는 서버에 사용됩니다. 짧은 게임에 필요한 시간 정확도를 위해서는 과잉이라고 생각합니다.
존 맥도날드

@Gilson, 클라이언트가 서버의 시간을 합리적으로 추정하고 두 클럭이 거의 같은 속도로 진행되는 한, 문제를 느끼지 않아야합니다. 클라이언트 나 서버가 상대방에게 작업을 보내면 현지 시간을 보냅니다. 수신 측에서 메시지는 항상 과거에 있어야하며 과거 이벤트로 해석해야합니다. 즉, 위치, 속도 (크기 + 방향) 및 시간과 같은 패킷의 모든 정보가 필요합니다. 그런 다음 퍽을 그곳에 놓고 퍽을 과거에서 현재로 이동할 수 있습니다. 내가 채팅 중입니다 btw
John McDonald
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.