简体   繁体   中英

Unexpected values with writeUTF and readUTF in Java

I have a server listening to two different ports, after a connection is accepted, it saves the combination nameOfClient - Socket into an hashMap. After that it starts a method in a loop to check which client is sending a message and who is the receiver of that message, it retrieves the the socket value from the hash map and use it to initialize a DataOutputStream to that socket.

The problem is that the server only receives the first two messages and they contain strange values. eg. Client 1 writeInt(1) to the server but on the other side an apparently random value is received.

The class sending data is:

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);
   }
}

The code for the server is:

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;
                }

There's another class in the same package of Game.java that connects to the server. The game is started succesfully by another client, after that the messages cannot be correctly received.

As stated in comments, your reads and writes are not symmetrical. If you call writeInt() there must be a corresponding readInt() . If you call writeUTf() there must be a corresponding readUTF() . And so on for all the other datatypes. And all these things must happen in the same order at both ends.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM