2017-01-22 6 views
1

2つの異なるポートをリッスンしているサーバーがあり、接続が受け入れられた後、nameOfClient - Socketの組み合わせがhashMapに保存されます。 その後、ループ内のメソッドを起動して、どのクライアントがメッセージを送信しているのか、そして誰がそのメッセージの受信者であるのかを調べ、ハッシュマップからソケット値を取得し、それを使用してそのソケットへのDataOutputStreamを初期化します。JavaでwriteUTFとreadUTFで予期しない値が発生しました

問題は、サーバーが最初の2つのメッセージのみを受信し、奇妙な値が含まれていることです。例えば。クライアント1のwriteInt(1)をサーバに送信しますが、反対側では明らかにランダムな値が受信されます。データを送信する

クラスは次のとおりです。

public class Game { 
List <Player> players = new ArrayList<Player>(); 

int size; 


public Game() { 

(...game code here...) 
public void sendUpdatedTableValues(int nP, int nF, int nS, int sc) 
{ 

    /* string,byte,stringa,primitivo del messaggio 
    string - mittente; byte - tipo di messaggio; stringa - ricevente; prim - messaggio 

    */ 
    try { 

     DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream()); 

     dataOut.writeUTF("Pista " + Lane.laneNum); 
     dataOut.writeInt(1); 
     dataOut.writeUTF("Amministrazione"); 
     dataOut.writeInt(nP); 
     dataOut.writeUTF("-"); 
     dataOut.writeInt(nF); 
     dataOut.writeUTF("-"); 
     dataOut.writeInt(nS); 
     dataOut.writeUTF("-"); 
     dataOut.writeInt(sc);   
     dataOut.flush(); 


    } catch (IOException ex) { 
     Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 



    /** 
    * This method send the player's number of strikes 
    * this method has ID byte = 3 
    * @param nP - Player Number 
    * @param nS - Strike Number 
    */ 
public void sendStrikeCounter(int nP, int nS) 
{ 
    try {  
     DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream()); 
     dataOut.writeUTF("Pista " + Lane.laneNum); 
     dataOut.writeInt(3); 
     dataOut.writeUTF("Amministrazione"); 
     dataOut.writeInt(nP); 
     dataOut.writeUTF("-"); 
     dataOut.writeInt(nS);      
     dataOut.flush(); 

    } catch (IOException ex) { 
     Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

/** 
* This method updates result table on server 
* this method has ID byte= 4 
* @param nP - Player Number 
* @param nF - Frame Number 
* @param res - Frame result 
*/ 
public void sendUpdatedResultsTable(int nP, int nF, int res) 
{ 
    try {  
     DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream()); 
     dataOut.writeUTF("Pista " + Lane.laneNum); 
     dataOut.writeInt(4); 
     dataOut.writeUTF("Amministrazione"); 
     dataOut.writeInt(nP); 
     dataOut.writeUTF("-"); 
     dataOut.writeInt(nF);      
     dataOut.writeUTF("-"); 
     dataOut.writeInt(res); 
     dataOut.flush(); 

    } catch (IOException ex) { 
     Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

/** 
* This method send the player's number of spares 
* this method has ID byte = 5 
* @param nP - Player Number 
* @param nS - Spare Number 
*/ 
public void sendSpareCounter(int nP, int nS) 
{ 
    try {  
     DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream()); 
     dataOut.writeUTF("Pista " + Lane.laneNum); 
     dataOut.writeInt(5); 
     dataOut.writeUTF("Amministrazione"); 
     dataOut.writeInt(nP); 
     dataOut.writeUTF("-"); 
     dataOut.writeInt(nS);      
     dataOut.flush(); 

    } catch (IOException ex) { 
     Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

サーバーのコードは次のとおりです。

public class Server { 

public static List <Player> players = new ArrayList <Player>(); 
public static HashMap <String, List<Player>> laneHashMap = new HashMap<String, List<Player>>(); 


ServerSocket adminListener; 
ServerSocket clientListener; 

public static void main(String[] args) throws IOException { 
    System.out.println("Server bowling avviato:\n"); 

    Server server = new Server(); 

    /** 
    * The port 9090 is reserved for the admin client, the other port is 
    * used by all the lane clients 
    */ 
    server.adminListener = new ServerSocket(9090); 
    server.clientListener = new ServerSocket(9898); 

    int clientNumber = 1; //Used to keep track of every single lane 

    //Create an HashMap used to store the name and the socket of the clients 
    HashMap<String, Socket> socketMap = new HashMap<>(); 

    /** 
    * The server starts two different threads that keep listening for 
    * incoming connections 
    */ 
    new threadAdminPort(server.adminListener, socketMap).start(); 
    new threadClientPort(server.clientListener, socketMap, clientNumber).start(); 

} 

/** 
* Used to listen to port 9090 
*/ 
private static class threadAdminPort extends Thread { 
    private ServerSocket adminListener; 
    private HashMap<String, Socket> socketMap; 

    public threadAdminPort(ServerSocket adminListener, HashMap<String, Socket> socketMap) { 
     this.adminListener = adminListener; 
     this.socketMap = socketMap; 

    } 

    @Override 
    public void run() { 
     try { 
      while (true) { 
       new Handler(adminListener.accept() , socketMap).start(); 
      } 
     } catch (IOException e) { 
      System.out.println("Errore di accept: " + e); 
     } finally { 
      try { 
       adminListener.close(); 
      } catch (IOException ex) { 
       Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
       } 
     } 

    } 
} 

/** 
* Used to listen to port 9898 
*/ 
private static class threadClientPort extends Thread { 
    private ServerSocket clientListener; 
    private HashMap<String, Socket> socketMap; 
    private int clientNumber; 

    public threadClientPort(ServerSocket clientListener , HashMap<String, Socket> socketMap , int clientNumber) { 
     this.clientListener = clientListener; 
     this.socketMap = socketMap; 
     this.clientNumber = clientNumber; 

    } 

    @Override 
    public void run() { 
     try { 
      while (true) { 
       new Handler(clientListener.accept() , socketMap , clientNumber++).start(); 
      } 
     } catch (IOException e) { 
      System.out.println("Errore di accept: " + e); 
     } finally { 
      try { 
       clientListener.close(); 
      } catch (IOException ex) { 
       Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
       } 
     } 

    } 
} 


/** 
* A private thread to handle requests on a particular socket. 
*/ 
private static class Handler extends Thread { 
    Socket socket; 
    HashMap<String, Socket> socketMap; 
    int clientNumber; 

    //Set true only if it is received a endOfGame message 
    boolean endOfGame = false; 

    /** 
    * This constructor is meant to be used by the lane clients. 
    */ 
    public Handler(Socket socket, HashMap<String, Socket> socketMap , int clientNumber) throws IOException { 
     this.socket = socket; 
     this.socketMap = socketMap; 
     this.clientNumber = clientNumber; 

     String clientName = "Pista " + clientNumber; 

     synchronized(socketMap) { 
     socketMap.put(clientName, socket); 
     } 

     //Send laneNum to the client 
     DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream()); 
     dataOut.writeInt(clientNumber); 

     System.out.println("- Pista " + clientNumber + " connessa -\nPronta per giocare"); 
    } 

    /** 
    * This constructor is meant to be used by the admin client as it 
    * provides no clientNumber variable. 
    */ 
    public Handler(Socket socket , HashMap<String, Socket> socketMap) { 
     this.socket = socket; 
     this.socketMap = socketMap; 

     String clientName = "Amministrazione"; 

     synchronized (socketMap) { 
     socketMap.put(clientName, socket); 
     } 

     System.out.println("- Client Amministrazione connesso -"); 
    } 

    /** 
    * This function is shared by both the admin client and the lane clients 
    */ 

    @Override 
    public void run() { 

      forwardMessage(); 


      try { 
       socket.close(); 
      } catch (IOException ex) { 
       Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
       } 

     if(clientNumber==0) 
      System.out.println("Connessione con il client amministrazione terminata"); 

     else  
     System.out.println("Connessione con il client " + clientNumber + " terminata"); 
    } 

    private void forwardMessage() { 

     Set set = socketMap.entrySet(); 
     Iterator iterator = set.iterator(); 

     //The following are the fixed fields of a message 
     String sender = null; 
     String receiver = null; 
     int messageType = 100; 

     //while(iterator.hasNext()) 
     while(true){ 
     for(Map.Entry<String, Socket> entry : socketMap.entrySet()){ 
     // Map.Entry mapEntry = (Map.Entry)iterator.next(); 

      Socket tempRecSocket = (Socket) entry.getValue(); 
      System.out.println("Il valore di tempRecSocket è "+ tempRecSocket); 
      DataInputStream dataIn; 
      DataOutputStream dataOut; 

      try { 
       dataIn = new DataInputStream(tempRecSocket.getInputStream()); 

       //Analyze and understand what type of message it is and who is 
       //the sender and the receiver 
       sender = dataIn.readUTF(); 
       messageType = dataIn.readInt(); 
       System.out.println("Sender ricevuto "+ sender); 
       receiver = dataIn.readUTF(); 
       System.out.println("Receiver ricevuto " + receiver); 


       switch (messageType) { 
        case 0: 
         { 
          //player 1 
          boolean start = dataIn.readBoolean(); 
          String namezero = dataIn.readUTF(); 
          int shoeszero = dataIn.readInt(); 
          String cf = dataIn.readUTF(); 
          //player 2 
          int shoesone = dataIn.readInt(); 
          String nameone = dataIn.readUTF(); 
          //player 3 
          int shoestwo = dataIn.readInt(); 
          String nametwo = dataIn.readUTF(); 
          //player 4 
          int shoesthree = dataIn.readInt(); 
          String namethree = dataIn.readUTF(); 
          //player 5 
          int shoesfour = dataIn.readInt(); 
          String namefour = dataIn.readUTF(); 
          //player 6 
          int shoesfive = dataIn.readInt(); 
          String namefive = dataIn.readUTF(); 
          laneHashMap.put(receiver, players); //insert in hashmap lane data 
          laneHashMap.get(receiver).add(new Player(0,namezero,shoeszero,cf)); //add player0 in players list7 
          laneHashMap.get(receiver).add(new Player(1,shoesone,nameone)); 
          laneHashMap.get(receiver).add(new Player(2,shoestwo,nametwo)); 
          laneHashMap.get(receiver).add(new Player(3,shoesthree,namethree)); 
          laneHashMap.get(receiver).add(new Player(4,shoesfour,namefour)); 
          laneHashMap.get(receiver).add(new Player(5,shoesfive,namefive)); 
          Socket tempSndSocket = (Socket) socketMap.get(receiver); 
          System.out.println("Il valore di tempSndSocket è "+ tempSndSocket); 
          dataOut = new DataOutputStream(tempSndSocket.getOutputStream()); 
          dataOut.writeUTF(sender); 
          dataOut.writeInt(messageType); 
          if(messageType!=0) 
           System.out.println("Valore di messageType "+ messageType); 
          dataOut.writeUTF(receiver); 
          dataOut.writeBoolean(start); 
          for (int i = 0;i<6;i++) 
          { 
           laneHashMap.get(receiver).get(i).setInitialTable(); 
           dataOut.writeUTF(laneHashMap.get(receiver).get(i).getName()); 
           dataOut.writeInt(0); //separatore 

          }  dataOut.flush(); 
          // dataOut.close(); 
          System.out.println("Il server ha inviato correttamente il messaggio di tipo 0"); 
          break; 
         } 
        case 1: 
         { 
          System.out.println("Il server ha ricevuto correttamente il messaggio di tipo 1 ed ora provvederà all'invio"); 
          //sendUpdatedTableValues 
          int playerNumber = dataIn.readInt(); 
          dataIn.readUTF(); 

          int frameNumber = dataIn.readInt(); 
          dataIn.readUTF(); 
          int shotNumber = dataIn.readInt(); 
          dataIn.readUTF(); 
          int score = dataIn.readInt(); 
          System.out.println("Ho ricevuto: 1 - "+ playerNumber + "2 - framenumber "+ frameNumber+ "3 - shotNumber" + shotNumber+ "4 - score "+ score); 

          //update local player data 
          laneHashMap.get(sender).get(playerNumber).setTable(frameNumber, shotNumber, score); 
          System.out.println("In questo turno il giocatore ha totalizzato "+ laneHashMap.get(sender).get(playerNumber).getTable(frameNumber, shotNumber)); 
          Socket tempSndSocket = (Socket) socketMap.get(receiver); 
          dataOut = new DataOutputStream(tempSndSocket.getOutputStream()); 
          dataOut.writeUTF(sender); 
          dataOut.writeInt(messageType); 
          dataOut.writeUTF(receiver); 
          dataOut.writeInt(playerNumber); 
          dataOut.writeUTF("-"); 
          dataOut.writeInt(frameNumber); 
          dataOut.writeUTF("-"); 
          dataOut.writeInt(shotNumber); 
          dataOut.writeUTF("-"); 
          dataOut.writeInt(score); 
          break; 
         } 

         break; 
       } 

別のクラスには、サーバに接続しGame.javaの同一パッケージ内にあります。ゲームは別のクライアントによって正常に開始された後、メッセージを正しく受信できません。

+0

私は何かが間違っているかもしれませんが、あなたは5の整数と5つの文字列を書いている間に4つの整数と3つの文字列を読んでいます。これは完全なコードではありません(もしそうなら、完全なコードを投稿してください)か、それはあなたの問題かもしれません。 – n247s

+1

stringの場合はstringを、intの場合はintを読み込む必要があります。文字列をint型として読み込むと、ゴミが出ます。そして、バイナリ形式を書いているので、テキスト形式を追加することにはあまり効果がありません。私はそれを落とすだろう。 –

+0

あなたの書き込みがバッファされないので(おそらくそうするべきです)、 'flush()'を実行すると、フラッシュするバッファがないので何もしません。 –

答えて

0

コメントに記載されているとおり、読み取りと書き込みは対称ではありません。 writeInt()に電話する場合は、対応するreadInt()が必要です。 writeUTf()に電話する場合は、対応するreadUTF()が必要です。他のすべてのデータ型についても同様です。これらのことは両方とも同じ順序で行わなければなりません。

関連する問題