2

ゲーム プログラムのクラスを常に 33 ミリ秒ごとに更新する Java クライアントがあります。問題は、同じクラスを受け取り、同期する必要がある 2 つのクライアントを開くと、サーバーを最初に起動または接続したユーザーによって結果が異なることです。その後、値は決して変化しませんが、サーバーが書き込みクラスを両方に送信していることを(今)知っています。私の家庭教師の講義ノートには、このように行うように書かれています

ObjectInput input;
input  = new ObjectInputStream(socket.getInputStream());
serializableobject = (cast) input.readObject();
input.flush();

これは私が教えられた方法ですが、今ではそれを実装するようになりました(大学ではこれは必要ありませんでした)それは機能しません。私は文字通り何週間も何ヶ月も費やしてその理由を解明しようとしましたが、今日はなぜクラックしたと思いますが、それを修正する方法がわかりません. 基本的に最初から input.flush(); ObjectInput または ObjectInputStream には存在しないように見えるので、それを省略してテストしたところ、ブレークポイントを使用してクラスが美しく表示され、サーバークラスが送信されたことを確認し、ゲーム設定クラスのすべての変数を設定しました。サーバーからのこのクラスの次の更新で問題が発生しますが、解決するのに何年もかかりました。私が信じていることは、(私が諦めなければ)最初に送信されたオブジェクトを読み取り、それを入力ストリームに保持することです。次に、同じメソッドを呼び出すと、最初のオブジェクトが再び返されます。これは、家庭教師が講義スライドで言っているように、フラッシュしないためだと思います。出力ストリームには、私が使用するフラッシュがあります。また、ObjectInput と ObjectInputStream の両方を調べたところ、フラッシュ、代替、またはストリーム内の次のオブジェクトに移動する方法を確認できませんでした。後者は、ストリームがメモリ不足になる可能性があるまで継続的に成長するため、とにかく良い考えだとは思いません。とにかく、受信クラスとサーバーをここに示します。後者は、ストリームがメモリ不足になる可能性があるまで継続的に成長するため、とにかく良い考えだとは思いません。とにかく、受信クラスとサーバーをここに示します。後者は、ストリームがメモリ不足になる可能性があるまで継続的に成長するため、とにかく良い考えだとは思いません。とにかく、受信クラスとサーバーをここに示します。

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

public class BaseServer 
{
        private String result = null;

        //for serializable class input stream
        ObjectInput input;


     // Declare client socket
        Socket clientSocket = null;         

     // Declare output stream and string to send to server 
        DataOutputStream os = null;


     // Declare input stream from server and string to store input received from server
        BufferedReader is = null;
        String responseLine;

    //get ip
        String serverAddress ;                                    

    // Create a socket on port 5000 and open input and output streams on that socket
    public void  setUpNetwork(String serverAd)
    {          
        try
        {
            serverAddress = serverAd;
            clientSocket = new Socket(serverAddress, 5000);

            //string
            os = new DataOutputStream(clientSocket.getOutputStream());          
            is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            //serial
            input = new ObjectInputStream( clientSocket.getInputStream() );

        } 
        catch (UnknownHostException e)
        {
            System.err.println("Don't know about host: hostname");
        }
        catch (IOException e)
        {
            System.err.println("Couldn't get I/O for the connection to: hostname");
        }      
    }

    /*
     * Used to communicate with server
     * takes message to send and the object expecting the response
     * 1 simple method to replace all but one of the below v1 methods
     */
    public BaseSerialDataObjects serverTalk(String message){
        sendStringMessage(message);

        try {   
            BaseSerialDataObjects bSO =  (BaseSerialDataObjects) input.readObject();            

            return  bSO;
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }


    ////////Old v.1 methods for interacting with servers. I have now changed my mind
    //and am using strings to send messages and serializable objects as return messages 
    //I have left these in as I have plans to reuse the most of the code in this game

    public String read(){
          // Write data to the socket
          if (clientSocket != null && os != null && is != null)
            {
             try
                {                           
                    os.writeBytes("ok \n");

                    return is.readLine(); // my bit   
                }
                catch (UnknownHostException e)
                {
                    System.err.println("Trying to connect to unknown host: " + e);
                }
                catch (IOException e)
                {
                    System.err.println("IOException:  " + e);
             }
          }
        return responseLine;
       }          

    //Sends messages to the server
    public void sendStringMessage(String message){
        // Write data to the socket
        if (clientSocket != null && os != null && is != null){
            try {                        
                os.writeBytes( message + "\n" );                                 
                }
            catch (UnknownHostException e){
                System.err.println("Trying to connect to unknown host: " + e);
                }
            catch (IOException e) {
                System.err.println("IOException:  " + e);
                }
            }   
        }          

    /*
     * V.1 method idea am leaving in for an option in future games
     */
    public  String getStringResult(String returnMessage)
   {    
       String tempHolder = read();
       if(tempHolder!=null)
       {
       String[] array = tempHolder.split("\\s+");
       if(array[0].trim().equalsIgnoreCase(returnMessage))
       {
           result = null;      
           tempHolder = "";

          for(int i = 1; i < array.length;i++)
          {           
              tempHolder = tempHolder +  array[i] + " ";        
          }
        return tempHolder.trim();
       }
       else return null;
       }
       else
         {
           return null;
           }

   }   

    public synchronized void setResult(String res)
    {
       result = res; 
    }    

    public void closeConnections()
   {
    // Close the input/output streams and socket
       try{
        os.close();
        is.close();
        clientSocket.close(); 
       }catch(Exception e)
       {
           System.err.println("Exception: " + e);
       }
   }
}

行: BaseSerialDataObjects bSO = (BaseSerialDataObjects) input.readObject();

以下の戻りbSO行にブレークポイントを配置したもので、サーバーにブレークポイントを配置し、クライアントを作成するクラスを返す直前に取得した異なる値をチェックしたにもかかわらず、最初と同じ値を持つクラスを常に表示します検査中にハングアップするので、正しいスレッドとクラス、およびすべてを確認できます

サーバー:

import java.io.*;
import java.net.*;
import java.*;
import java.util.regex.*;

public class TCPserver implements Runnable 
{
    static Socket server = null;    

    private static final int possibleNumberOfPlayers = 8;
    private static final int amountOfPlayerInfoHeld = 6;
    private int threadNumber;

    private static ServerSettings gameSettings = new ServerSettings();
    private static int numberOfSettings = 4;

    //position 0 = name;
    //position 1 = angle;
    //position 2 = position x
    //position 3 = position y
    //position 4 = state

    //position 5 = state in relation to server
    //POssible states: 
        // connected
    static PlayerPositionsSerial positions = new PlayerPositionsSerial();

    public static void main( String args[] )
    {
       positions.playersArray = new String [possibleNumberOfPlayers][amountOfPlayerInfoHeld];

      // Declare a server socket and a client socket for the server
      ServerSocket service = null;

      // Try to open a server socket on port 5000
      try
       {
         service = new ServerSocket(5000);
            server = service.accept();
            Thread t0 = new Thread (new TCPserver(0));
           t0.start();
            server = service.accept();
            Thread t1 = new Thread (new TCPserver(1));
           t1.start();
            server = service.accept();
            Thread t2 = new Thread (new TCPserver(2));
           t2.start();      
            server = service.accept();
            Thread t3 = new Thread (new TCPserver(3));
           t3.start();
            server = service.accept();
            Thread t4 = new Thread (new TCPserver(4));
           t4.start();          
            server = service.accept();
            Thread t5 = new Thread (new TCPserver(5));
           t5.start();
            server = service.accept();
            Thread t6 = new Thread (new TCPserver(6));
           t6.start();          
            server = service.accept();
            Thread t7 = new Thread (new TCPserver(7));
           t7.start();
            /*server = service.accept();
            Thread t8 = new Thread (new TCPserver(8));
           t8.start();  */      


      }
      catch (IOException e)
       {
         System.out.println(e + "Error B");
      }        


        }

    public void run()
    {
    // Declare an input stream and String to store message from client      
        BufferedReader is;
        String line;

        // Declare an output stream to client       
       DataOutputStream os;

        String thr = Integer.toString(threadNumber);

      // Create a socket object from the ServerSocket to listen and accept
      // connections. Open input and output streams
      try
       {
            ObjectOutput output;
            output = new ObjectOutputStream( server.getOutputStream() );

            is = new BufferedReader( new InputStreamReader(
                                         server.getInputStream()));



           //if( (line = is.readLine()) != null )
            while( (line = is.readLine()) != null )
            {
                if(line != null)
                {                   
                    switch(rules(line)){
                    case "playertable": 
                        output.writeObject( positions );    

                        break;
                    case "gamesettings": 
                        output.writeObject( gameSettings );
                        break;
                    case "servernumber": 
                        StringReturnSerial string = new StringReturnSerial();
                        string.s = Integer.toString(threadNumber);
                        output.writeObject(string);
                        break;
                        default:
                            System.out.println("line didnt select anything");
                            break;
                    }
                }output.flush();

            }

            // Comment out/remove the stream and socket closes if server is to remain live. 

         is.close();

      }  
      catch (IOException e)
       {
         System.out.println(e + "Error B");         
      }         
    }

    public TCPserver(int tNumber)
    {
        threadNumber = tNumber;
    }

    private synchronized void changeArray(int row, int col, String value)
    {
        positions.playersArray[row][col]  = value;
    }

    private synchronized String readArray(int row, int col)
    {
        return positions.playersArray[row][col];
    }   

    private String rules(String lineIn)
    {
        try {
             String[] splitArray = lineIn.split("\\s+");

                 switch(splitArray[0])
                 {
                    case "SIGNIN":

                        positions.playersArray[threadNumber][0] = splitArray[1];
                        positions.playersArray[threadNumber][4] = "normal";
                        positions.playersArray[threadNumber][amountOfPlayerInfoHeld-1] = "connected";                       
                        addPlayer();
                        gameSettings.gameStartTime = System.currentTimeMillis() + 10000;

                        return "gamesettings";

                    case "ok":
                    // just for reply, do nothing response heard "ok"
                        break;
                    case "MATCHMAKE":
                            positions.playersArray[threadNumber][amountOfPlayerInfoHeld -1] = "matchmake";
                            gameSettings.gameState = "matchmake";
                            return "playertable";

                    case "READY":

                        positions.playersArray[threadNumber][amountOfPlayerInfoHeld -1] = "ready";

                        return "gamesettings";


                    case "REQUESTSTART":

                          boolean goAhead = true;
                            for(int i = 0 ; i < gameSettings.numberOfConnectedPlayers; i++)
                            {
                                if(positions.playersArray[i][amountOfPlayerInfoHeld-1] != "ready")
                                {
                                    goAhead = false;
                                }
                            }                       

                            if(goAhead)
                            {
                                long start = System.currentTimeMillis( );
                                start = start + 10000;
                                gameSettings.gameStartTime = start;
                            }

                            return "gamesettings";

                        case "GETPOS":

                            return "playertable";                           

                        case "UPDATEPOS":

                            //heres where to notice crashes and check for wins etc...
                            positions.playersArray[threadNumber][1] = splitArray[1];
                            positions.playersArray[threadNumber][2] = splitArray[2];
                            positions.playersArray[threadNumber][3] = splitArray[3];
                            positions.playersArray[threadNumber][4] = splitArray[4];
                            return "playertable";

                        case "GETSETTINGS":
                            return "gamesettings";

                        /*case "SENDSETTINGS":

                            // updates settings 
                            for (int i = 1; i < splitArray.length; i++){
                                switch(i){
                                case 1: 
                                    gameSettings.gameState = splitArray[i];
                                    break;
                                case 2: 
                                    gameSettings.winningNumberOfLaps = Integer.parseInt(splitArray[i]);
                                    break;
                                case 3: 
                                    gameSettings.winString = splitArray[i];
                                    break;
                                case 4: 
                                    gameSettings.gameStartTime = Long.parseLong(splitArray[i]);
                                    break;
                                case 5: 
                                    gameSettings.numberOfConnectedPlayers = Integer.parseInt(splitArray[i]);
                                    break;
                                }
                            }

                            returnString = "gamesettings";
                            break;
                            */

                        case "GETSERVERNUMBER":
                            return "servernumber";                          

                        case "PLAYING":
                            gameSettings.gameState = "playing";

                            break;
                        case "SERVERPLAYERSTATEUPDATE":

                            int crashed = 0;
                            positions.playersArray[Integer.parseInt(splitArray[1])][5] = splitArray[2];
                            for(int i  = 0; i < gameSettings.numberOfConnectedPlayers;){

                                //takes into account possibility of people leaving game
                                if(positions.playersArray[i][5] != null){
                                    if(positions.playersArray[i][5] == "explode"){
                                        crashed++;
                                    }
                                }
                            }
                            if(crashed == gameSettings.numberOfConnectedPlayers)
                                gameSettings.gameState = "explode";

                            return "gamesettings";  

                        default:
                            System.err.println("Rule Not Found: " + splitArray[0]);
                            break;

                 }

        } catch (PatternSyntaxException ex) {

                System.err.println("error C: " + ex);
        }

        return null;
    }

    public synchronized void addPlayer()
    {
        gameSettings.numberOfConnectedPlayers++;
    }

    public synchronized int getNumberOfPlayers()
    {
        return gameSettings.numberOfConnectedPlayers;
    }

    public synchronized void removePlayer()
    {
        gameSettings.numberOfConnectedPlayers--;
    }
}

前もってありがとう ジョン・ハリス

4

2 に答える 2

1

に加えてflush、必要ですreset( ObjectOutputStream内)。オブジェクト ストリーム、読み取りと書き込み、読み取りと書き込みのすべてを保存します。2 つの問題: 1 つは、両側でメモリが不足することです。2 つ目は、同じオブジェクトを 2 回送信すると、読み取られたオブジェクトには最初に読み取られたデータが含まれます。2 回目の書き込みでは、データではなく、(本質的に) オブジェクト ID のみが送信されます。を呼び出すたびにリセットを呼び出しますwriteObject

于 2013-07-10T20:14:23.810 に答える