将多个客户端连接到服务器时Java流损坏

时间:2019-04-25 15:42:05

标签: java multithreading sockets multiplayer

说明

我目前正在尝试用Java创建一个多人游戏,最多可以有五个玩家一起玩。 问题是,当我尝试将多个客户端连接到服务器时,出现异常,并且服务器不再工作。 一次只有一个客户,一切正常。

所以我需要的是一个服务器,一次最多可以处理五个玩家,并且客户端应始终从该服务器获取一些新的游戏数据。 每隔几秒钟(已连接的播放器等)。 以下代码中的“游戏数据”是我通过对象流发送的字符串。 通常,我会发送一个包含所有游戏数据的对象,但是使用字符串,我会遇到相同的问题。

我正在努力解决一个问题,即几天之内只有一个客户端可以连接而没有任何错误发生,并且我没有找到解决问题的方法。 我看到有诸如java.nio或ExecutorService之类的东西,但是我并不太了解,所以我不知道它们是否可以提供帮助。

我制作了一个较小的程序,该程序模拟了我在较大程序中遇到的相同问题。 要启动服务器,需要启动GameMultiPlayerCreate.java类,对于客户端,则需要启动Client.java类。

我是Socket的新手,所以如果不需要某些东西或可以做一些更好的事情,请告诉我。

所以当我连接两个或多个客户端时出现的错误是:

java.io.StreamCorruptedException: invalid stream header: 00050131
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at Server.waitForData(Server.java:89) //I highlighted that in the code with a comment
    at Server.loopWaitForData(Server.java:49)
    at Server.run(Server.java:34)
    at java.lang.Thread.run(Unknown Source)

代码

  • GameMultiPlayerCreate.java:如果客户端连接,应启动服务器线程
public class GameMultiPlayerCreate {
    ServerSocket socketServer = null;

    static String settingIp = "localhost";
    static String settingPort = "22222";
    static byte settingPlayers = 5;
    public static int connectedPlayers = 0;

    public static void main(String[] args) {
        try {
            GameMultiPlayerCreate objGameMultiPlayerCreate = new GameMultiPlayerCreate();
            objGameMultiPlayerCreate.createServer();
        } catch (NumberFormatException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void createServer() throws NumberFormatException, UnknownHostException, IOException, InterruptedException {
        while (connectedPlayers < settingPlayers) {
            socketServer = new ServerSocket(Integer.parseInt(settingPort), 8, InetAddress.getByName(settingIp));
            System.out.println("Server is waiting for connection...");

            Socket socket = socketServer.accept();
            new Thread(new Server(socket)).start();

            Thread.sleep(5000);
            socketServer.close();
        }
    }
}
  • Server.java:这是一个类,应该为每个连接的客户端(客户端处理程序)创建一个新的线程
public class Server implements Runnable {
    protected static Socket socket = null;

    private int loops;
    private int maxLoops = 10;
    private int timeout = 10000;
    protected static boolean killThread = false;
    private boolean authenticated = true; //true for testing

    protected static String ip;
    protected static int port;

    public Server(Socket socket) throws IOException {
        Server.socket = socket;
    }

    public void run() {
        try {
            socket.setSoTimeout(timeout);
        } catch (SocketException e) {
            System.out.println("Error while trying to set Socket timeout. ");
            System.out.println("Closing Thread..." + Thread.currentThread());
            disconnectClient();
        }
        if (!killThread) {
            GameMultiPlayerCreate.connectedPlayers = GameMultiPlayerCreate.connectedPlayers + 1;
            loopWaitForData();
        }
    }

    private void disconnectClient() {
        System.out.println("Kicking Client... " + Thread.currentThread());
        killThread = true;
        GameMultiPlayerCreate.connectedPlayers = GameMultiPlayerCreate.connectedPlayers - 1;
    }

    public void loopWaitForData() {
        while (!killThread) {
            System.out.println(maxLoops + ", " + loops);
            if (maxLoops - loops > 0) {
                try {
                    waitForData();
                } catch (SocketTimeoutException e) {
                    System.out.println("Error occurred while waiting for Data. Thread disconnected? Sending reminder. " + Thread.currentThread());
                    if (!authenticated) {
                        System.out.println("Kicking Client: Not authenticated");
                        disconnectClient();
                    } else {
                        commandReminder();
                    }
                } catch (ClassNotFoundException | IOException e) {
                    loops = loops + 1;
                    System.out.println("Error occurred while waiting for Data. Waiting for more Data. " + Thread.currentThread());
                    e.printStackTrace();
                    loopWaitForData();
                }
            } else if (maxLoops - loops == 0) {
                System.out.println("Error occurred while waiting for Data. Maximum trys reached. Disbanding connection. " + Thread.currentThread());
                disconnectClient();
                loops = loops + 1;
            } else {
                System.out.println("Closing Thread..." + Thread.currentThread());
                disconnectClient();
            }
        }
    }

    private void commandReminder() {
        System.out.println("Reminder");
        try {
            String code = new String("0");
            ObjectOutputStream outputObject = new ObjectOutputStream(Server.socket.getOutputStream());
            outputObject.writeObject(code);
        } catch (IOException e) {
            System.out.println("Error occurred while trying to authenticate Client: " + e + " in " + Thread.currentThread());
        }
    }

    public void waitForData() throws IOException, ClassNotFoundException {
        String code;
        System.out.println("Waiting for Data...");
        //Next line is where the error occurres
        ObjectInputStream inputObject = new ObjectInputStream(socket.getInputStream());
        while ((code = (String) inputObject.readObject()) != null) {
            System.out.println("Received Data...");
            System.out.println("Input received: " + code);
            return;
        }
    }
}
  • Client.java:这是客户端
public class Client {
    public static Socket socket = new Socket();

    private int loops = 0;
    private int maxLoops = 10;
    private static boolean killThread = false;

    private String ip;
    private int port;

    public Client(String receivedIp, String receivedPort) {
        ip = receivedIp;
        port = Integer.parseInt(receivedPort);
        try {
            System.out.println("Trying to connect to Server...");
            socket.connect(new InetSocketAddress(ip, port));
            System.out.println("Connected!");
        } catch (IOException e) {
            System.out.println("Error occurred while trying to connect to Server.");
        }
        loopWaitForData();
    }

    public static void main(String[] args) {
        @SuppressWarnings("unused")
        Client objClient = new Client("localhost", "22222");
    }

    public void loopWaitForData() {
        while (!killThread) {
            System.out.println(maxLoops + ", " + loops);
            if (maxLoops - loops > 0) {
                try {
                    waitForData();
                } catch (IOException | ClassNotFoundException e) {
                    loops = loops + 1;
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e1) {

                    }
                    System.out.println("Error occurred while waiting for Data. Waiting for more Data. " + Thread.currentThread());
                    e.printStackTrace();
                    loopWaitForData();
                }
            } else if (maxLoops - loops == 0){
                System.out.println("Error occurred while waiting for Data. Maximum trys reached. Disbanding connection. " + Thread.currentThread());
                try {
                    socket.close();
                } catch (IOException e) {
                    System.out.println("Failed to close Socket " + Thread.currentThread());
                }
                loops = loops + 1;
            } else {
                System.out.println("Closing Thread..." + Thread.currentThread());
                killThread = true;
            }
        }
    }

    public void waitForData() throws IOException, ClassNotFoundException {
        InputStream input = socket.getInputStream();
        ObjectInputStream inputObject = new ObjectInputStream(input);
        String code;
        System.out.println("Waiting for Data...");
        while ((code = (String) inputObject.readObject()) != null) {
            System.out.println("Received Data...");
            System.out.println("Input received: " + code);

            answer();
            return;
        }
    }

    private void answer() {
        try {
            String code = new String("1");
            ObjectOutputStream outputObject = new ObjectOutputStream(socket.getOutputStream());
            outputObject.writeObject(code);
        } catch (IOException e) {
            System.out.println("Error occurred while trying to answer: " + e + " in " + Thread.currentThread());
        }
    }
}

0 个答案:

没有答案