0


Java でクライアント サーバー ゲーム ("SET" と呼ばれる) を開発しました。

デバッグ プロセス中に、非常に厄介な問題に遭遇しました。
クライアントとサーバーの両方を同じマシンで実行すると (クライアントは localhost に接続します)、ゲームは素晴らしく動作します (サーバーと多くのクライアントを実行した場合も同様です)。

しかし、クライアントとサーバーを 2 台の別々のマシンで実行すると、クライアントとサーバーの両方が Inputstream の readLine メソッドでハングします。

writeBytes メソッドを使用してデータを書き込んでいることに言及しますが、データ行は常に \n で終了します (前述のように、システムは 1 台のマシンで完全に動作します!)

システムのアーキテクチャは次のとおりです。

public SetServer(){
        this.deck = initCardsList();
        Collections.shuffle(this.deck);

        shownCards = new Card[12];
        for(int i = 0; i<12; i++){
            Card c = this.deck.removeFirst();
            shownCards[i]=c;
        }
        while(!isSetOnTable()){
            Card c = this.deck.removeFirst();
            this.deck.addLast(shownCards[0]);
            shownCards[0]=c;
        }

        playersQueue = new LinkedList<String>();

        clients = new LinkedList<ServerOperation>();
        try{
            ServerSocket welcomeSocket = new ServerSocket(6789);
            while(true)
            {
                if(currNumOfPlayers<5){
                    System.out.println("Waiting for connection...");
                   Socket connectionSocket = welcomeSocket.accept();
                   String line = (new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()))).readLine();
                   currNumOfPlayers++;
                   playersQueue.addLast(line);

                   ServerOperation client = new ServerOperation(connectionSocket,this, line);
                   clients.add(client);
                   Thread t = new Thread(client);
                   t.start();  //<--- This thread listens to client's request
                   notifyPlayersAdded(line,new DataOutputStream(connectionSocket.getOutputStream())); //<-----This method sends 3 lines of data
                }

            }
        }
        catch(Exception e){
                System.out.println(e.getMessage());
            }
    }

ServerOperation の run メソッド:

public void run(){
        if(socket==null){
            return;
        }
        else{
            try{

        //      this.out.writeBytes("NewConnection:" + this.parent.STATUS+"\n");
            //  this.parent.notifyCards();
                while(true){
                    String line = this.br.readLine();
                    String command = line.split(":")[0];
                    if(command.equals("SetRequest")){                       
                        String[] cards = line.substring(line.indexOf(':')+1).split(" ");
                        Card c1,c2,c3;
                        c1 =  new Card(
                                CardShape.values()[(int)(cards[0].charAt(3)-'0')],
                                CardNumber.values()[(int)(cards[0].charAt(2)-'0')],
                                CardFill.values()[(int)(cards[0].charAt(1)-'0')],
                                CardColor.values()[(int)(cards[0].charAt(0)-'0')]);
                        c2 =  new Card(
                                CardShape.values()[(int)(cards[1].charAt(3)-'0')],
                                CardNumber.values()[(int)(cards[1].charAt(2)-'0')],
                                CardFill.values()[(int)(cards[1].charAt(1)-'0')],
                                CardColor.values()[(int)(cards[1].charAt(0)-'0')]);
                        c3 =  new Card(
                                CardShape.values()[(int)(cards[2].charAt(3)-'0')],
                                CardNumber.values()[(int)(cards[2].charAt(2)-'0')],
                                CardFill.values()[(int)(cards[2].charAt(1)-'0')],
                                CardColor.values()[(int)(cards[2].charAt(0)-'0')]);
                        this.parent.checkIfSetAndNotify(c1,c2,c3,this.playerId);
                    }


                }
            }

            catch(Exception e){
                System.out.println(e.getMessage());
            }
        }

クライアントのコード:

    public SetClient()
    {
        String sentence;
        this.myCards = new LinkedList<Card>();
        try{
          String modifiedSentence;
          BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
          clientSocket = new Socket("10.0.0.3", 6789);
          DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
          BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
          outToServer.flush();
          String name = sayHelloAndGetUserName();
          outToServer.writeBytes(name);
          outToServer.flush();

          sentence = inFromServer.readLine();
          sayWelcome(sentence);
          ClientOperation clnOper = new ClientOperation(clientSocket,this);
          Thread t = new Thread(clnOper);
          t.start(); //<---this thread listens to the server for messages (suppose
//to catch the first 3 lines. In practice, catches only the first one.

          while(!GameOver)
          {
              try{
                    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //<-----listens to the user's input
                    String line = br.readLine();
                    String[] choices = line.split(" ");
                    int c1 = Integer.parseInt(choices[0]);
                    int c2 = Integer.parseInt(choices[1]);
                    int c3 = Integer.parseInt(choices[2]);
                    sendSetMessage(outToServer,c1,c2,c3);
                }
                catch(Exception ex){
                    System.out.println("Error listening to system.in...");
                }
          }

        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
    }

ClientOperation のコード:

public void run()
    {
        if(socket==null){
            return;
        }
        else{
            try{
                this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                while(true){
                    String line = this.br.readLine();
                    String command = line.split(":")[0];
                    String value = line.split(":")[1];
                    if (command.equalsIgnoreCase("Deck"))
                    {
                        ConvertStringToCards(value);
                        this.parent.PopulateCards(shownCards);
                    }

                    else if (command.equalsIgnoreCase("Points"))
                    {
                        System.out.println("Points: " + value);
                    }

                    else if(command.equalsIgnoreCase("NewPlayer")){
                        System.out.println(value + " has joined the game !\n");
                    }

                    else if(command.equalsIgnoreCase("Hint")){
                        this.parent.printHint(ConvertStringToHint(value));
                    }
                }
            }
            catch(Exception e){
                System.out.println(e.getMessage());
            }
        }
    }

一般に、クライアント サーバー プロジェクトが 1 台のマシンでは完全に動作するのに、2 台のマシンではハングする理由は何でしょうか?
PSクライアントとサーバーを別々のマシンで段階的にデバッグしているときも、完全に機能します。

前もって感謝します、

4

1 に答える 1

1

ローカルホストの問題でない場合は、ファイアウォールが存在するかどうかを確認して無効にしてから再度確認し、次に netstat を実行して、サーバーがループバックだけでなくすべてのインターフェイスでリッスンしているかどうかを確認します。

Linuxでは、次を試すことができます:

netstat -nat | grep 6789

Windows Power Shell でも動作する可能性があります。サーバーが外部IPで実行/リッスンしていて、クライアントがまだ接続できず、ファイアウォールが無効になっている場合は、wiresharkをインストールして、ネットワークで何が起こっているかを確認してください。

于 2012-07-20T08:02:53.700 に答える