java - Java 中 writeUTF 和 readUTF 的意外值

标签 java sockets server dataoutputstream

我有一个服务器监听两个不同的端口,在接受连接后,它将 nameOfClient - Socket 组合保存到 hashMap 中。 之后,它在循环中启动一个方法来检查哪个客户端正在发送消息以及谁是该消息的接收者,它从 HashMap 中检索套接字值并使用它来初始化该套接字的 DataOutputStream。

问题是服务器只接收前两条消息,并且它们包含奇怪的值。例如。客户端 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 的同一包中还有另一个类连接到服务器。另一个客户端成功启动游戏,之后无法正确接收消息。

最佳答案

正如评论中所述,您的读取和写入不对称。如果您调用writeInt(),则必须有一个相应的readInt()。如果您调用writeUTf(),则必须有一个相应的readUTF()。对于所有其他数据类型依此类推。所有这些事情必须在两端以相同的顺序发生。

关于java - Java 中 writeUTF 和 readUTF 的意外值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41794043/

相关文章:

java - Websocket 仅限 Web 应用程序?

javascript - 在 Node js 中调用 java 方法

Java ServerSocket 只接受 2 个连接

java - "Exception in thread "AWT-EventQueue-0 "java.lang.NullPointerException"Java 套接字编程中的错误

java - 如何通过Java套接字正确设置服务器部分?

java - IntelliJ - 自动完成不适用于新包

python .select 正在阻塞

c# - 不使用 System.Net.Sockets 时出现套接字错误

java - 1 台本地主机上 2 台 Virtual Box 计算机之间的 TCP 连接

c++ - OpenSSL 套接字 : Select always returns 0