我有一个服务器侦听两个不同的端口,在接受连接后,它将组合nameOfClient - Socket保存到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的同一个包中有另一个连接到服务器的类。该游戏由另一个客户端成功启动,之后无法正确接收消息。
答案 0 :(得分:0)
如评论中所述,您的读写不是对称的。如果您致电writeInt()
,则必须有相应的readInt()
。如果您致电writeUTf()
,则必须有相应的readUTF()
。等等所有其他数据类型。所有这些事情必须在两端以相同的顺序发生。