2009-12-18 6 views
0

그래, 아직 게임을하고있다. (심지어 알파조차도 아니다.) 한 사람이 서버를 호스팅하고 다른 사람이 연결하는 1 대 1 게임이 있다고 가정한다. 하지만 지금은 코드가 너무 어슬렁 어서 무엇이든 할 수 없습니다. 누군가 그것을 살펴보고 속도를 높이는 방법을 말해 줄 수 있습니까? 추신 : 나는 또한 Slick2D 라이브러리를 사용하고 있습니다.누군가 Java에서 내 넷 코드의 속도를 높일 수 있습니까?

서버 :

import java.net.*; 
import java.io.*; 

public class SlickServer{ 
    public static void main(String[] args) throws IOException { 

     int MAX_PLAYERS = 3; 
     int playerNum = 0; 
     Player[] players = new Player[MAX_PLAYERS]; 
     players[0] = new Player(25,25); 
     players[1] = new Player(125,125); 
     players[2] = new Player(225,225); 
     ServerSocket serverSocket = new ServerSocket(4444); 
     boolean listening = true; 

     while(listening){ 
      System.out.println("Waiting to connect with: " + playerNum); 
      new ClientThread(serverSocket.accept(), players, playerNum).start(); 
      //stops here. 
      System.out.println("Connected with: " + playerNum + " Now incrementing"); 
      playerNum++; 
      System.out.println("Incremented to: " + playerNum); 
     } 



     serverSocket.close(); 
     System.exit(0); 
    } 
} 

서버 스레드 :

import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.*; 
import java.io.*; 

public class ClientThread extends Thread implements Runnable{ 
    Socket acceptedSocket; 
    Player[] players; 
    int playerNum; 

    public ClientThread(Socket acceptedSocket, Player[] players, int playerNum){ 
     super("ClientThread"); 
     this.acceptedSocket = acceptedSocket; 
     this.players = players; 
     this.playerNum = playerNum; 
    } 

    public void run(){ 
     try{ 

      Socket clientSocket = acceptedSocket; 
      System.out.println("Accepted. Now creating I/O."); 
      ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream()); 
      ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream()); 
      System.out.println("I/O with: " + playerNum + " working."); 
      out.writeInt(playerNum); 
      out.flush(); 

      while(true){ 
       if(playerNum == 0){ 
        players[0].x = in.readInt(); 
        players[0].y = in.readInt(); 
        out.writeInt(players[1].x); 
        out.writeInt(players[1].y); 
        out.flush(); 
       } 

       else if(playerNum == 1){ 
        players[1].x = in.readInt(); 
        players[1].y = in.readInt(); 
        out.writeInt(players[0].x); 
        out.writeInt(players[0].y); 
        out.flush(); 
       } 

       else if(playerNum == 2){ 
        players[2].x = in.readInt(); 
        players[2].y = in.readInt(); 
        out.writeInt(players[0].x); 
        out.writeInt(players[0].y); 
        out.flush(); 
       } 
      } 

     } 

     catch(Exception e){ 
      e.printStackTrace(); 
      System.exit(1); 
     } 


    } 


} 

클라이언트 :

import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 

import org.newdawn.slick.AppGameContainer; 
import org.newdawn.slick.BasicGame; 
import org.newdawn.slick.GameContainer; 
import org.newdawn.slick.Graphics; 
import org.newdawn.slick.Image; 
import org.newdawn.slick.Input; 
import org.newdawn.slick.SlickException; 

import java.io.*; 
import java.net.*; 


public class SlickClient extends BasicGame{ 

    int MAX_PLAYERS = 3; 
    int playerNum = 0; 
    Player[] players; 
    ClientThread ct; 

    int serverDelay = 15; 

    public SlickClient() 
    { 
     super("Client"); 
    } 

    @Override 
    public void init(GameContainer gc) 
      throws SlickException { 
     try{ 
      players = new Player[MAX_PLAYERS]; 
      players[0] = new Player(25,25); 
      players[1] = new Player(125,125); 

      ct = new ClientThread(players); 
      ct.start(); 
      ct.setPriority(Thread.MAX_PRIORITY); 

      playerNum = ct.playerNum; 
     } 

     catch(Exception e){ 
      e.printStackTrace(); 
     } 

    } 

    @Override 
    public void update(GameContainer gc, int delta) 
      throws SlickException 
    { 
     Input input = gc.getInput(); 

     if(input.isKeyDown(Input.KEY_A)) 
     { 
      players[playerNum].x-=5; 
     } 

     if(input.isKeyDown(Input.KEY_D)) 
     { 
      players[playerNum].x+=5; 
     } 

     if(input.isKeyDown(Input.KEY_W)) 
     { 
      players[playerNum].y-=5; 
     } 

     if(input.isKeyDown(Input.KEY_S)) 
     { 
      players[playerNum].y+=5; 
     } 



    } 

    public void render(GameContainer gc, Graphics g) 
      throws SlickException 
    { 
     g.fillRect(players[0].x, players[0].y, 50, 50); 
     g.fillRect(players[1].x, players[1].y, 50, 50); 

    } 

    public static void main(String[] args) 
      throws SlickException 
    { 
     AppGameContainer app = 
      new AppGameContainer(new SlickClient()); 

     app.setAlwaysRender(true); 
     app.setTargetFrameRate(30); 
     app.setDisplayMode(800, 600, false); 
     app.start(); 
    } 
} 

class ClientThread extends Thread implements Runnable{ 
    Socket socket; 
    Player[] players; 
    int playerNum; 
    ObjectOutputStream out; 
    ObjectInputStream in; 

    public ClientThread(Player[] players){ 
     super("ClientThread"); 

     try{ 

      socket = new Socket("98.203.176.196", 4444); 
      out = new ObjectOutputStream(socket.getOutputStream()); 
      in = new ObjectInputStream(socket.getInputStream()); 
      this.players = players; 
      playerNum = in.readInt(); 
      System.out.println(playerNum); 

     } 

     catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 

    public void run(){ 
     try{ 
      while(true){ 
       if(playerNum == 0){ 
        try{ 
         out.writeInt(players[0].x); 
         out.writeInt(players[0].y); 
         out.flush(); 
         players[1].x = in.readInt(); 
         players[1].y = in.readInt(); 
        } 

        catch(Exception e){ 
         e.printStackTrace(); 
        } 
       } 

       else if(playerNum == 1){ 
        try{ 
         out.writeInt(players[1].x); 
         out.writeInt(players[1].y); 
         out.flush(); 
         players[0].x = in.readInt(); 
         players[0].y = in.readInt(); 
        } 

        catch(Exception e){ 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 

     catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 
} 
+4

아마도 응용 프로그램을 프로파일 링하고 느린 부분이 무엇인지 알려주거나 (b) 응용 프로그램을 프로파일 링하는 방법을 물어보십시오. –

답변

2

클라이언트가 서버의 원격 시스템에있을 때만 지연이 있습니까? 그렇다면 상자들 사이에 핑 (ping) 시간이 적당합니다. 그런 다음 야생 추측을하고 여기서 Nagle의 알고리즘을 사용하고 있다고 말할 수 있습니까? 푸시하는 데이터는 매우 작습니다 (writeInt).

빠른 수정을 원할 경우 BufferedOutputStream 중개를 사용해 볼 수도 있지만 소켓에서 Nagle을 비활성화 할 수도 있습니다.

Socket.setTcpNoDelay (true);

+0

소켓을 "localhost"에 연결해도 문제가 없지만 IP로 설정하면 지연이 발생합니다. 세트 지연이 조금 도움이되었습니다. – William

1

당신이 데이터를주고받을 ObjectOutputStreamObjectInputStream이 아닌 다른 뭔가를 사용하여 시도 적이 있습니까? 이것들을 사용하면 객체 직렬화 및 비 직렬화가 포함되며, DataOutputStream을 사용하면 속도가 빨라질 수 있습니다.

+0

BAOS는 ByteArrayOutputStream이 아닌 DataInputStream 및 DataOutputStream을 의미합니까? 실제로 데이터로 무엇이든 할 수 있습니까? –

+0

죄송합니다. 내가 생각했던 것입니다. 고마워요. –

+0

또는 훨씬 빠른 것으로 입증 될 수있는 사용자 고유의 직렬화 및 직렬화 복원 방법을 작성하십시오 (데이터를 읽을 때 이전 버전과 새 버전이 호환되어야 함). 자세한 내용을 보려면 여기를 클릭하십시오. http://code.google.com/p/thrift-protobuf-compare/wiki/BenchmarkingV2 및 http://stackoverflow.com/questions/647779/high-performance-serialization-java-vs -google-protocol-buffers-vs – Kounavi

1

당신이 제공하는 코드가 불완전합니다 ... 나는 이것을 할 것이고 그것을 어떻게 할 것인지를 알기에 당신이 볼 것을 확신 할 수 있습니다 ... 그러나 우리는 우리가 가진 것과 함께 일할 것입니다. .

1) 클라이언트와 서버 모두에서 동일한 시스템에서 실행하십시오. 여전히 느린가요? 2) 컴퓨터간에 핑 (ping)하고 속도가 인 방법을 확인하십시오. 3) 앱을 프로파일 링하십시오.

# 1이 네트워킹 문제인지 확인하는 데 도움이됩니다. 동일한 시스템에있는 클라이언트와 서버 모두 네트워크를 제거합니다.

# 2는 네트워킹 문제인지 확인하는 데 도움이됩니다. 핑 (ping)이 좋지 않으면 게임이 느려집니다.

# 3은 어렵지만 코드에서 느린 위치의 결과를 제공합니다.

프로파일로 Visual VM을 살펴보십시오 (또는 netbeans를 프로파일 링하는 경우 ... 이클립스는 아마도 플러그인 일 수도 있습니다).

프로파일 링에 대해서는 서버로 시작하여 느린 것을보고 클라이언트로 이동하십시오. 나는 서버에서 계속 진행되는 일이 적기 때문에 그 일이 어떻게 진행되고 있는지보기 쉬워야한다고 제안한다.

1

흠, 여러 가지를 즉시 시도 할 수 있지만 원하는 작업을 수행해야합니다.

먼저 클라이언트와 서버 모두 매우 긴 루프 상태입니다. 보통 당신이 사용하는 루프는 루프가 너무 많은 CPU를 소비하지 못하도록 막기 위해 각 패스에서 최소한의 시간 동안 잠을 잘 수 있어야합니다.

둘째, 비 차단 I/O를 사용해야합니다 (읽기 전에 각 클라이언트의 입력을 확인하십시오).

마지막으로 Java 네트워킹과 관련된 학습 과제를 시작하거나 비표준 통신 프로토콜을 필요로하는 특정 목적이 없으면 단순히 확장 할 수있는 서버 프레임 워크를 사용하는 것이 좋습니다. 이렇게하는 쉬운 방법은 Jetty 또는 Tomcat으로 서버 측을 빌드하고 클라이언트 측에 Apache HTTPClient를 사용하는 것입니다.

전용 서버를 사용하기로 결정했다면 Core Java 책이나 Java Networking (O'Reilly) 책의 간단한 서버 프레임 워크가 더 나은 기반을 제공 할 것입니다.

희망이 있습니다.

1

왜 느린 지에 따라 다릅니다. 다음은 몇 가지 제안 사항입니다.

  1. 비 차단 I/O 만 사용하십시오. 이 규칙의 전문화로 RPC를 절대로 사용하지 마십시오.
  2. 적절한 경우 클라이언트 측 예측을 수행하는 것이 좋습니다. 클라이언트 측 예측은 클라이언트가 수행하고자하는 것이 괜찮을 것으로 가정하고, 클라이언트가 괜찮 았던 것처럼 클라이언트에 그릴 것입니다. 대부분의 경우 네트워크로 연결된 모든 게임이 이것을 사용합니다.
  3. 실시간 게임에서 플레이어간에 '동기화'된 상태가 아니라는 점을 인정하십시오. 그것은 단지 일어나지 않을 것입니다.

또한 "느림"을 의미합니다. 코드가 불량 프레임을 제공한다는 것을 의미합니까? 움직임이 등록되기까지 오랜 시간이 걸리니? 이 점을 파악하면 최적화의 첫 걸음이 될 것입니다.

행운을 빈다. 네트워킹 게임에 경험이있는 전문 개발자의 경우에도 전투 게임을 네트워크를 통해 반응 적으로 처리하는 것은 어려운 작업입니다. 지연을 숨길 수 있도록 게임 디자인을 수정해야 할 수도 있습니다. 네트워크를 통해 불가능한 일은있을 수 있습니다.

1

원하는 경우 데이터 그램 소켓을 사용해 볼 수 있습니다. 근본적인 패킷이 떨어지면, 그냥 사라지지만, 위치를 업데이트하고 있기 때문에 괜찮을 것입니다.

관련 문제