문제

소켓 서버와 플래시 게임 클라이언트를 작성하고 있습니다. 게임에는 움직임 및 회전과 같은 실시간 명령이 필요합니다. 다른 클라이언트가 이동/회전 클라이언트와 많은 것을 많이 사용하지 않기 때문에 이러한 명령을 클라이언트에 최대한 빨리 보내는 것이 중요합니다.

이것은 Nagle 산술로 인한 문제의 예입니다.

메모:이 명령의 의미를 이해하려면 아래 명령 표를 참조하십시오.

첫 번째는 내가 이사 한 배입니다 (앞으로 + 오른쪽으로 이동, 앞으로 수령되었지만 오른쪽은 아닙니다)

클라이언트 보내기 명령 :

84796: Sending data: 2#4
84796: Sending data: 2#2
84904: Sending data: 2#3
84904: Sending data: 2#0
86187: Sending data: 2#4
86188: Sending data: 2#2
86374: Sending data: 2#3
86404: Sending data: 2#0

명령을받는 클라이언트 :

79244: Raw receive: 3#3#4$
79244: New command: 3#3#4
79398: Raw receive: 3#3#2$3#3#3$3#3#0$
79399: New command: 3#3#2
79399: New command: 3#3#3
79399: New command: 3#3#0
80635: Raw receive: 3#3#4$
80635: New command: 3#3#4
80908: Raw receive: 3#3#2$3#3#3$3#3#0$
80908: New command: 3#3#2
80908: New command: 3#3#3
80908: New command: 3#3#0

"순간"은 내가 말하려는 것을 의미하지 않는 이상한 용어이지만, 여기에서는 이전 명령 후 밀리 초의 시간이 보입니다.

  1. 클라이언트 A (Moment : 0), Client B (모멘트 : 0)에 의해 전송을 앞으로 이동

  2. 클라이언트 A (모멘트 : 0), 클라이언트 B (모멘트 : 155)에 의해 우회전 보내기

  3. 클라이언트 A (모멘트 : 108), 클라이언트 B (모멘트 : 0)에 의한 보내기 전송 중지

  4. 클라이언트 A (모멘트 : 0), 클라이언트 B (모멘트 : 0)에 의해 보내지는 중지 중지

  5. 고객 B (Moment : 1283), Client B (모멘트 : 1236)에 의해 전송을 앞으로 이동

  6. 클라이언트 A (순간 : 1), 클라이언트 B (Moment : 273)에 의해 우회전 보내기

  7. 클라이언트 A (모멘트 : 186), 클라이언트 B에 의해 수신 된 이동 중지 이동 (순간 : 0)

  8. 클라이언트 A (모멘트 : 30), 클라이언트 B (모멘트 : 0)에 의해 전송 중지 중지

이것은 명령에 해당하는 명령 테이블입니다.

클라이언트-> 서버

2# (movement info)
0) now not turning
1) now turning left
2) now turning right
3) now not moving
4) now moving forward

서버-> 클라이언트

3# (movement info)
[shipId]#
0) now not turning
1) now turning left
2) now turning right
3) now not moving
4) now moving forward

따라서, 당신이 볼 수있는 것은 "nagle"때문에 명령이 완전히 동기화된다는 것입니다. 이로 인해 Start Movement 명령과 동시에 다른 클라이언트가 STOP Movement 명령을 수신하여 해당 플레이어가 전혀 움직이지 않도록합니다.

그렇기 때문에 이러한 명령을 TCP 서버에서 가능한 빨리 실시간으로 전송해야합니다. 쉬운 수정은 단순히 nagle을 비활성화하는 것입니다. 그러나 나는 가지고있다 Googled (TCP 메시지에 대한 그의 제안은 부분적으로 내 시스템에서 구현되지만 타이밍과 관련이 없음) 조금은 사람들이 Nagle을 비활성화하는 것을 절대적으로 권장하지 않는다는 것을 알았습니다.

이 원인에 대한 Nagle 알고리즘을 비활성화해서는 안되는 것이 사실입니까? 대신 다른 솔루션을 찾아야합니까? 왜 안 돼)?

미리 감사드립니다. - 톰

도움이 되었습니까?

해결책

TCP_NODELAY를 사용하여 해당 소켓의 Nagle 알고리즘을 끕니다. 현대식 OS에는 시스템 전체에서 비활성화 할 설정이 있으며 이다 눈살을 찌푸 리지만, 당신이 낮은 대기 시간이 필요하다는 것을 알고있는 소켓으로하지 말아야 할 이유는 없습니다.

setsockopt (tcp_nodelay)

다른 팁

가능한 빨리 여야하는 경우 UDP를 사용해야합니다.

그러나 TCP는 보증을 제공합니다 배달 그리고 주문하다 UDP는 아무것도 제공하지 않습니다.

그 지점은 비판적으로 이 응용 프로그램의 중요한 점이므로 자신의 승인/재시도 명령 순서 메커니즘을 맨 위에 계층화해야합니다.

TCP를 고수하려면 tcp__nodelay가 도움이됩니다. 게임이 발전함에 따라 TCP가 TCP_Nodelay없이 적합한 데이터 스트림이 필요할 수 있습니다.

RFC1006은 TCP 스트림을 통해 패킷을 보내는 메커니즘을 공식화합니다.

스위치, 라우터, ISP의 Swithcgear 등. 더러운 작은 짐승은 패킷을 읽을 수 있으므로 자유를 취하고 때때로 다시 작성합니다.

더 많은 네트워크를 제공 할 수있는 접근 방식을 위해 RTP (UDP를 통해 실행)를 살펴보십시오.

당신의 목표가 배가 모든 사람의 화면에서 똑같은 일을하게하는 것이라면, 당신은 포지션 업데이트를 보내야 할 것입니다. 당신은 단지 클라이언트 A가했기 때문에 다음과 같이 가정 할 수 없습니다.

  • 왼쪽으로 돌아
  • 100ms를 기다립니다
  • 회전을 중지하십시오

해당 클라이언트 B는 정확히 동일한 100ms 지연을 보게 될 것입니다. Nagle 버퍼링은 이것을 더욱 극단적으로 만듭니다. 그러나 항상 지터와 다양한 지연이있을 것입니다.

당신은 정말로 다음과 같은 것을 보내야합니다.

  • (나는 제목 Z1과 함께 X1, Y1 위치에있다) 좌회전
  • (나는 제목 Z2와 함께 위치 X2, Y2에있다)

클라이언트가 지속적으로 재 동기화되도록합니다.

Windows가 구현됩니다 지연된 ACK Nagle뿐만 아니라. 이를 통해 개별 TCP 메시지에 200ms의 지연이 추가로 제공 될 수 있습니다. 내가 아는 한, 레지스트리 키 (및 경우에 따라 레지스트리 키를 활성화하기 위해 핫 패치를 통해)를 제외하고는 Windows에서 이것을 변경할 수 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top