0

クライアント/サーバーのJavaゲームを使用しています。たくさんのコードがあり、十分な量を与えながら、できるだけ貼り付けないようにしています。

サーバーを最初に起動したときは、CPUは必要ありません。私の最初のゲームクライアントが接続すると、25%にジャンプします(これは、それが行うことにはかなり高いようですが、それはまだ私の主な関心事ではありません)。問題は、クライアントが切断されても、サーバーアプリのCPU使用率が25%のままであるということです。

サーバーはクライアントから名前を取得し、プレーヤーから常にx、y座標を受け取ります。

サーバーの起動後に実行される実際のサーバーのコードは次のとおりです:(過度のインデントについて事前に謝罪します)

 TCPServer(int port) {
                try
                {
                        tcpSock = new ServerSocket(port);
                        int z = 0;
                        while(true)
                        {
                                Socket sock = tcpSock.accept();
                                sock.setKeepAlive(true);  
                                clientList.addElement(new TcpClient(sock));
                                clientList.get(z).cr.start();
                                clientList.get(z).cw.start();
                                clientList.get(z).packs.addElement("?");
                                while(!clientList.get(z).cr.nameRecieved)
                                {
                                //do nothing untill client has provided it's name
                                }
                                playerList.addElement(new player(sock.getInetAddress(), clientList.get(z).cr.playerName));                                     
                                playerList.get(z).id=z;
                                playerList.get(z).name=clientList.get(z).cr.playerName;
                                clientList.get(z).packs.addElement("2 " + z);
                                for(int j =0; j<playerList.size();j++)
                                    {
                                   String status;
                                   if(playerList.get(j).Connected)
                                       status = "1";
                                   else
                                       status = "0";

                                        addToQueue("3 " + playerList.get(j).id + " "
                                                + playerList.get(j).name + " " + playerList.get(j).x + " " + playerList.get(j).y + " " + 
                                                playerList.get(j).area + " " + status + " " );                     
                                    }
                                z++;
                                addToQueue("4 " + z);
                        }    
                }

                catch (IOException e) {   
                        System.out.print(e);   
                }   
        }

そして、これが各クライアントに対して実行されるコードです。読みやすさのためにその大部分をコメントアウトしました。コードはさまざまな位置情報を計算して更新するだけです。このクラスのどこかで問題が発生していると思います。

  public class TcpClient {
                Socket sock;
                ObjectInputStream in;
                ObjectOutputStream out;
                ClientRead cr;
                ClientWrite cw;
                public Vector<String> packs = new Vector<String>();
                 TcpClient(Socket s) {
                        this.sock = s;
                        try
                        {
                            sock.setKeepAlive(true);
                        }
                        catch(Exception e)
                        {
                            System.out.print(e);
                        }
                        cr = new ClientRead();
                        cw = new ClientWrite();
                }
                public class ClientRead extends Thread {
                     public boolean nameRecieved = false;
                     public boolean reading = true;
                String playerName;
                    public void run(){
                        try{
                            in  = new ObjectInputStream(sock.getInputStream());
                            while(sock.isConnected() && reading)
                            {
                               //code to retrieve and update user location
                            }
                        }
                        catch(Exception e){
                                System.out.print(e);
                    }
                }
        }

そして最後に、クライアントに情報を書き込むための短いクラス:

public class ClientWrite extends Thread {
                 public boolean writing = true;
                    public void run() {
                        try{

                            out = new ObjectOutputStream(sock.getOutputStream());
                            out.flush();
                            while(sock.isConnected() && writing)
                            {
                                out.flush();
                                while(!packs.isEmpty())
                                {
                                    out.writeObject(packs.firstElement());
                                    System.out.print(packs.firstElement());
                                    packs.remove(0);
                                    out.flush();
                                }
                            }

                        }
                        catch(Exception e)
                        {
                            System.out.print(e);
                        }
                    }
                }

たくさんのコードがあることは知っていますが、誰かが(特にスレッドで)すぐに飛び出すものを見つけた場合、それは私が得ている動作を説明することができます。要約すると、クライアントが接続するまで、サーバーは0%CPUのままです。最初のクライアントが接続した後、接続数に関係なく、CPUは25%〜30%のままです。ただし、すべてのクライアントが切断されると、CPUは0に戻るのではなく、その25%〜30%のままになります。

4

1 に答える 1

5

問題はここにあります:

while(!clientList.get(z).cr.nameRecieved)
{
    //do nothing untill client has provided it's name
}

CPUをスモークするスピンループです。あなたはこれをすべて間違ってやっています。ソケットを受け入れたらすぐに、それを処理するために新しいスレッドを開始する必要があります。そのスレッドは、クライアントがプロトコルハンドシェイクの一部としてその名前を提供するまでブロックしてから、データ構造を更新する必要があります。受け入れループは、接続の受け入れとスレッドの開始以外は何も実行しないでください。

于 2013-02-07T04:18:32.330 に答える