Java StreamCorrupted при подключении более одного клиента к серверу - PullRequest
0 голосов
/ 25 апреля 2019

Объяснение

В настоящее время я пытаюсь создать многопользовательскую игру на Java, в которой одновременно могут играть до пяти игроков. Проблема в том, что когда я пытаюсь подключить несколько Клиентов к моему Серверу, я получаю Исключение, и Сервер больше не работает. С одним клиентом одновременно все работает нормально.

Итак, мне нужен сервер, который может одновременно обслуживать до пяти игроков, и клиенты всегда должны получать с сервера новые игровые данные. каждые несколько секунд (подключенные игроки и т. д.). «Данные игры» в приведенном ниже коде - это строка, которую я посылаю через поток объектов. Обычно я отправляю объект, содержащий все игровые данные, но со строкой у меня возникает та же проблема.

Я борюсь с проблемой, что только один Клиент может подключиться без каких-либо ошибок, возникающих в течение нескольких дней, и я не нашел решения своей проблемы. Я видел, что есть такие вещи, как java.nio или ExecutorService, но я не особо разбирался в них, поэтому не знаю, могут ли они помочь.

Я создал меньшую программу, которая имитирует ту же проблему, что и моя большая программа. Чтобы запустить сервер, необходимо запустить класс GameMultiPlayerCreate.java, а для клиента - класс Client.java.

Я новичок в Sockets, поэтому, если что-то не нужно или что-то можно улучшить, пожалуйста, дайте мне знать.

Итак, ошибка, которую я получаю при подключении двух или более клиентов:

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());
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...