简体   繁体   English

客户端/服务器套接字Java(模式MVC)未向客户端发送正确的信息

[英]Client/Server Socket Java (pattern MVC) doesn't send correct information to the Client

I'm writing a game but now I'm a problem with server/client socket. 我正在写游戏,但现在服务器/客户端套接字有问题。 The game works well when I play in local and also when I play online with RMI. 当我在本地玩游戏以及通过RMI在线玩游戏时,该游戏效果很好。 The problem there is when I try to implements the socket (I must do also socket). 当我尝试实现套接字时存在问题(我也必须执行套接字)。 This is how I've implemented the code (I use the pattern Model-View-Controller): 这就是我实现代码的方式(我使用模式Model-View-Controller):

SERVER: Class SocketServerCreate: create the server and then create a Thread to receive the connection (SocketServerConnection) that then create another Thread to receive the message by all the client (SocketServerReceive). SERVER:类SocketServerCreate:创建服务器,然后创建一个线程以接收连接(SocketServerConnection),然后创建另一个线程以接收所有客户端的消息(SocketServerReceive)。 The Server instantiate also an object that implements Observer that is called by the model to send information to the client (SocketServerOutput). 服务器还实例化一个实现Observer的对象,该对象由模型调用以将信息发送到客户端(SocketServerOutput)。

CLIENT: Class SocketClientCreate: open the connection with the server, then create a Thread to receive message by the server and instantiate a class that implements Observer that is called by the view to send information to the Server. 客户:类SocketClientCreate:打开与服务器的连接,然后创建一个线程以接收服务器的消息,并实例化一个实现Observer的类,该类由视图调用以将信息发送到服务器。

The problem is that the update method of the Server that is in the class SocketServerOutput is called a lot of time, but it must be called only one time to send the message to the client. 问题在于,在SocketServerOutput类中的Server的更新方法被调用了很多次,但是只有一次才能将消息发送到客户端。 To be clare I post all the code of the Server and the Client. 为方便起见,我发布了服务器和客户端的所有代码。

SocketServerCreate SocketServerCreate

/*
 * This class creates the server.
 */

public class SocketServerCreate {

private static final int PORT = 5000;
private ArrayList<ObjectOutputStream> arrayPlayerSocket;
private SocketServerOutput outputServer;

public SocketServerCreate(Model model){

    ServerSocket serverSocket;
    Controller controller = new Controller(model);
    arrayPlayerSocket = new ArrayList<ObjectOutputStream>();
    try {
        serverSocket = new ServerSocket(PORT);
    } catch (IOException e) {
        System.out.println("Error during the creation of the Server.\n" +     e.getStackTrace());
        return;
    }

    outputServer = new SocketServerOutput(this, controller);

    SocketServerConnection connectionServer = new SocketServerConnection(this, serverSocket, controller);
    Thread receiveServerThread = new Thread(connectionServer);
    receiveServerThread.start();

}

public void addPlayerSocket(ObjectOutputStream outputStream){
    arrayPlayerSocket.add(outputStream);
}

public ArrayList<ObjectOutputStream> getArrayPlayerSocket(){
    return (ArrayList<ObjectOutputStream>) arrayPlayerSocket;
}

public SocketServerOutput getSocketServerOutput(){
    return outputServer;
}

}

SocketServerOutput SocketServerOutput

/*
 * This class manages the object that must be send to the client.
 */

public class SocketServerOutput implements Observer {

ArrayList<ObjectOutputStream> arrayPlayersSocket;
SocketServerCreate socketServerCreate;
Controller controller;
private ObjectOutputStream outputMessage = null;

public SocketServerOutput(SocketServerCreate socketServerCreate, Controller controller){
    this.socketServerCreate = socketServerCreate;
    this.controller = controller;
}


@Override
public void update(Observable o, Object arg) {

    if(o.equals(controller.getModel().getModelChanges())){
        arrayPlayersSocket = socketServerCreate.getArrayPlayerSocket();
        Iterator<ObjectOutputStream> arrayIterator = arrayPlayersSocket.iterator();
        while(arrayIterator.hasNext()){
            outputMessage = (ObjectOutputStream)arrayIterator.next();
            try {
                outputMessage.writeObject(arg);
                outputMessage.flush();
                /*if(arrayPlayersSocket.indexOf(outputMessage) != controller.getTurn().getCurrentPlayer()){
                    ModelChanges modelChanges = new ModelChanges();
                    modelChanges.spegniBottoniOnLine(false, false, false);
                    outputMessage.writeObject(modelChanges);
                    outputMessage.flush();
                }*/
            } catch (IOException e) {
                System.out.println("IOException while the server sends an object to the client!");
                return;
            }

        }

    }

}



}

SocketServerConnection SocketServerConnection

    public class SocketServerConnection implements Runnable {

private ServerSocket serverSocket;
private SocketServerCreate socketServerCreate;
private Controller controller;

public SocketServerConnection(SocketServerCreate socketServerCreate, ServerSocket serverSocket, Controller controller){

    this.socketServerCreate = socketServerCreate;
    this.serverSocket = serverSocket;
    this.controller = controller;
}

@Override
public void run() {

    while(true){

        try {
            Socket lastSocket = serverSocket.accept();
            ObjectOutputStream outputMessage = new ObjectOutputStream(lastSocket.getOutputStream());
            socketServerCreate.addPlayerSocket(outputMessage);
             //send to the view the index where the client is setted in the server array
            outputMessage.writeObject((Integer)socketServerCreate.getArrayPlayerSocket().lastIndexOf(outputMessage));
            outputMessage.flush();
            SocketServerReceive receiveServer = new SocketServerReceive(lastSocket, controller);
            Thread receiveThread = new Thread(receiveServer);
            receiveThread.start();  
        } catch (IOException e) {
            System.out.println("IOException while the server accept the client.\n" + e.getCause());
        }


    }

}

}

SocketServerReceive SocketServerReceive

public class SocketServerReceive implements Runnable {

private ObjectInputStream inputMessage = null;
private Controller controller;
private Object message;

public SocketServerReceive(Socket socket, Controller controller){
    this.controller = controller;
    System.out.println("Connection created with the client that has IP Address: " + socket.getInetAddress());

    if(inputMessage == null){
        try {
            inputMessage = new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            System.out.println("IOException while the server are creating a stream with the client.\n" + e.getCause());
        }
    }

}

@Override
public void run() {

    while(true){
        try {
            message = inputMessage.readObject();
            controller.receiveMessageView(message);
        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException in SocketServerReceive.\n" + e.getStackTrace());
            return;
        } catch (IOException e) {

        }
    }

}

}

SocketClientCreate SocketClientCreate

/*
 * This class starts a connection with the Server and then it creates two threads,
 * one to manage the input request, the other to manage the output request
 */

public class SocketClientCreate {

private static final int PORT = 5000;
private Socket serverSocket;
private int arrayIndex;
private SocketClientOutput outputClient;

public SocketClientCreate(String ipAddress, View view){

    try {
        serverSocket = new Socket(ipAddress, PORT);
    } catch (UnknownHostException e) {
        System.out.println("UnknownHostException during the connection of the Client at the Server");
        return;
    } catch (IOException e) {
        System.out.println("IOException during the connection of the Client at the Server");
        return;
    }

    outputClient = new SocketClientOutput(this, serverSocket, view);


    SocketClientReceive receiveClient = new SocketClientReceive(this, serverSocket, view);
    Thread receiveThread = new Thread(receiveClient);
    receiveThread.start();

}

public SocketClientOutput getOutputClient(){
    return outputClient;
}

public void setArrayIndex (Integer arrayIndex){
    this.arrayIndex = arrayIndex;
}

public int getArrayIndex(){
    return arrayIndex;
}

}

SocketClientOutput SocketClientOutput

/*
 * This class manages all the message that the client must send to the server. Its methods 
 * are called by update method.
 */

public class SocketClientOutput implements Observer {

private ObjectOutputStream outputMessage = null;
private View view;
private SocketClientCreate socketClientCreate;

public SocketClientOutput(SocketClientCreate socketClientCreate, Socket server, View view){

    this.view = view;
    this.socketClientCreate = socketClientCreate;
    if(outputMessage == null){
        try {
            outputMessage = new ObjectOutputStream(server.getOutputStream());
        } catch (IOException e) {
            System.out.println("IOException at the opening of the output stream between the client and the server.\n" + e.getCause());
            return;
        }
    }

}

/*
 * update receive an object from the view and send this object to the server.
 */
@Override
public void update(Observable o, Object arg) {

    if(o.equals(view)){
        /*
         * GESTIRE INDICE CREAZIONE GIOCATORE
         */
        try {
            outputMessage.writeObject(arg);
            outputMessage.flush();
        } catch (IOException e) {
            System.out.println("IOException while the client sends an object to the server.\n" + e.getCause());
            return;
        }

    }

}

}

SocketClientReceive SocketClientReceive

/*
 * This class waits an object from the server and then modify the view.
 */

public class SocketClientReceive implements Runnable {

private ObjectInputStream inputMessage = null;
private View view;
private SocketClientCreate socketClientCreate;
private Object message;

public SocketClientReceive(SocketClientCreate socketClientCreate, Socket server, View view){

    this.view = view;
    this.socketClientCreate = socketClientCreate;
    if(inputMessage == null){
        try {
            inputMessage = new ObjectInputStream(server.getInputStream());
        } catch (IOException e) {
            System.out.println("IOException at the opening of the input stream between the client and the server.\n"+e.getStackTrace());
        }
    }

}

@Override
public void run() {

    while(true){
        try {
            message = inputMessage.readObject();
            if(message instanceof Integer){
                socketClientCreate.setArrayIndex((Integer)message);
            }else if(message instanceof ModelChanges){
                ModelChanges modelChanges = (ModelChanges)message;
                view.getMappa().repaintView(modelChanges);
            }

        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException waiting a message from the server!\n"+e.getStackTrace());
            return;
        } catch (IOException e) {

        }
    }

}

}

I would advise you to create a boolean, that is enabled by default, but turn false when the server sends a message. 我建议您创建一个默认启用的布尔值,但在服务器发送消息时将其设置为false。 Then, when the server intends to send another message, turn it should turn true. 然后,当服务器打算发送另一条消息时,将其转为true。 Contact me if this was what you had in mind, or if you are looking for something else. 如果您有此想法,或者正在寻找其他东西,请与我联系。

        private Object lastMessage;
        private boolean hasSentMessage;

        @Override
        public void update(Observable o, Object arg) {
        //Check if the message is the same as the last message.
        if(!arg.equals(lastMessage))
            hasSentMessage = false;

        //Also check if it has already sent a message.
        if(o.equals(controller.getModel().getModelChanges()) && !hasSentMessage){
            arrayPlayersSocket = socketServerCreate.getArrayPlayerSocket();
            Iterator<ObjectOutputStream> arrayIterator = arrayPlayersSocket.iterator();
            while(arrayIterator.hasNext()){
                outputMessage = (ObjectOutputStream)arrayIterator.next();
                try {
                    outputMessage.writeObject(arg);
                    outputMessage.flush();

                    //State that the message has been sent.
                    hasSentMessage = true;
                    lastMessage = arg;

                    /*if(arrayPlayersSocket.indexOf(outputMessage) != controller.getTurn().getCurrentPlayer()){
                        ModelChanges modelChanges = new ModelChanges();
                        modelChanges.spegniBottoniOnLine(false, false, false);
                        outputMessage.writeObject(modelChanges);
                        outputMessage.flush();
                    }*/
                } catch (IOException e) {
                    System.out.println("IOException while the server sends an object to the client!");
                    return;
                }

            }

        }

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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