2012-03-09 2 views
12

저는 Java TCP 게임 서버를 가지고 있습니다. java.net.ServerSocket을 사용합니다. 모든 것이 잘 돌아가지만, 최근에 ISP는 업그레이드를했습니다. 패킷은 동일한 TCP 연결에 대해 매우 빠르며 강제로 닫습니다.내 ISP가 나를 보내기 전에 TCP 데이터를 버퍼에 넣습니다.

이 게임에서 트래픽이 많이있을 때 내 많은 선수가 무작위로 연결되는 이유는

(서버가 같은 사람을 동시에 2 개 패킷을 보낼 것이라는 점을 기회가 많이있을 때) 여기에 내가 무엇을 의미하는지의 예입니다 나는 같은 것을 할 경우, 내 ISP는 클라이언트와 서버 측에 아무 이유에 대한 접속을 닫습니다 :

tcpOut.print("Hello."); 
tcpOut.flush(); 

tcpOut.print("How are you?"); 
tcpOut.flush(); 

하지만 난 뭔가를 할 경우는 잘 작동합니다 이렇게 :

tcpOut.print("Hello."); 
tcpOut.flush(); 

Thread.sleep(200); 

tcpOut.print("How are you?"); 
tcpOut.flush(); 

또는이 : 그들은합니다 (ISP)는 서비스와 네트워크의 일부를 변경했을 때

tcpOut.print("Hello."); 
tcpOut.print("How are you?"); 
tcpOut.flush(); 

이 단지 몇 주 전에 시작했다. 나는 Wireshark를 사용하여 동일한 TCP 연결에 대해 두 패킷 사이에 적어도 ~ 150ms의 시간을 가져야한다는 것을 알아 차렸습니다. 그렇지 않으면 닫을 것입니다.

1)이 전화가 무엇인지 아십니까? 이름이 있니? 그것은 합법적입니까? send(PrintWriter out, String packetData);

2) 클라이언트로 전송하기 전에 데이터를 버퍼링 자바를 요청할 수있는 쉬운 해결책이 있습니까 :

지금은 내가라는 방법을 사용하는 것이 알고 내 게임 서버를 다시 작성해야? 또는 모든 것을 다시 쓸 필요없이 각 보내기 전에 150ms 기다리시겠습니까? 나는 약간의 인터넷 검색을했지만이 문제를 다루는 것을 찾을 수 없다. 이것에 대해 도움이되는 정보 또는 정보는 속도 최적화가 매우 중요하다는 점에서 정말 감사 할 것입니다. 고맙습니다.

+1

이것은 올바르게 들리지 않습니다. 로컬 TCP/IP 스택은 감지 된 네트워크 속도에 따라 보내는 데이터를 버퍼링하고 지연 시키며, tcpSetNoDelay를 망쳐 놓지 않는 한 일반적으로 패킷을 병합하여 더 이상 합칩니다. 강제 폐쇄가 있다고 생각하는 것은 무엇입니까? 그리고 사용자가 실제로 6 줄을 초당 입력 할 수 있습니까? 또는 모든 개행 후에 애플리케이션이 불필요하게 플러시되는 것입니까? – EJP

+1

의견을 보내 주셔서 감사합니다. 나는 100 %의 긍정적 인 ISP가 연결을 닫고있다, 나는 그것이 빨간색 재설정 패킷을 얻을 때 Wireshark에서 볼 수있다. 또한 몇 가지 테스트를 수행했습니다. 가끔씩 데이터가 하나의 패킷에 추가되었지만 (로컬 TCP/IP 스택), 때로는 서버가 플러시 할 때가 많지 않을 때가 있습니다. MMORPG 게임이므로지도에서 동시에 말하고 이동하고 공격 할 때 플러시가 많이 일어나므로 한 번에 두 개의 패킷이 동시에 한 명의 플레이어에게 전송되고 ISP가 닫습니다. 그 소켓. – Reacen

+0

그리고 "같은 시간"은 100ms 미만의 지연을 의미합니다. – Reacen

답변

3

마지막으로 flush 호출 타임 스탬프를 추적하기 위해 Writer 래퍼 구현을 만들 수 있습니다. 빠른 구현은 대기 호출을 추가하여 두 번의 연속 플러시 사이의 150ms 지연을 준수하는 것입니다.

public class ControlledFlushWriter extends Writer { 
    private long enforcedDelay = 150; 
    private long lastFlush = 0; 
    private Writer delegated; 

    public ControlledFlushWriter(Writer writer, long flushDelay) { 
     this.delegated = writer: 
     this.enforcedDelay = flushDelay; 
    } 

    /* simple delegation for other abstract methods... */ 

    public void flush() { 
     long now = System.currentTimeMillis(); 
     if (now < lastFlush + enforcedDelay) { 
      try { 
       Thread.sleep(lastFlush + enforcedDelay - now); 
      } catch (InterruptedException e) { 
       // probably prefer to give up flushing 
       // instead of risking a connection reset ! 
       return; 
      } 
     } 
     lastFlush = System.currentTimeMillis(); 
     this.delegated.flush(); 
    } 

} 

그것은 지금 포장하기에 충분합니다 작업-의 주위에 당신의 ISP의 QoS 모든 응용 프로그램을 다시 작성하지 않고이 ControlledFlushWriterPrintWriter 기존.

결국, 패킷이 긴급한 것으로 플래그를 지정하지 못하도록하는 것이 합리적이라고 생각됩니다. 이러한 조건에서는 공정한 QoS 링크 공유를 구현하기가 어렵습니다.

+0

대단히 감사합니다! – Reacen

5

ISP에서 이러한 서비스 품질 정책을 부과하고 ISP와 협상 할 방법이없는 경우 TCP/IP 스택 QoS 구성을 사용하여 사용자 측에서 규칙을 적용 할 것을 제안합니다.

플러시는 버퍼/TCP 창 상태가 무엇이든간에 보내도록 TCP 패킷을 긴급 (URG 플래그)으로 표시합니다. 지금 당신은 줄에 운영 체제 나 네트워크 장비 말할 필요로 하나

  • 무시 (또는 단순히 재설정) 이전 패킷이 지난 150 MS에 전송하고 필요한 경우 약간의 버퍼링을 수행하고있다 긴급 플래그
  • 은 긴급 패킷 연속 배달을 지연시켜 150ms 제약 조건을 준수합니다.

아마도 Windows 용 비싼 소프트웨어가있을 것입니다. 개인적으로 iptables 및 qdisc에서 appropriate QoS settings을 사용하는 Windows 워크 스테이션과 모뎀간에 Linux 상자를 라우터로 사용하는 것이 트릭을 수행 할 것이라고 생각합니다.

관련 문제