Блокировка Java Socket и ServerSocket Communication - PullRequest
0 голосов
/ 07 мая 2019

Я пытаюсь создать многопользовательскую игру с игровым сервером, работающим не более чем с 4 клиентами, используя java Socket и ServerSocket.В этом коде я ограничил число клиентов до 1 для тестирования и использовал модель блокирующего ввода-вывода для игрока и сервера.

Поток игрового сервера (реализует Runnable) получает объект Snake для snake [i] 'и переменная char для dirInput ' от каждого клиента, использующего поток ввода сокета, и отправляет массив объектов Snake snake 'и объект Apple apple 'с использованием потока вывода сокета.И объект Snake, и объект Apple являются сериализуемыми.

Здесь массив clientSocket состоит из всех подключенных клиентских сокетов, и эти сокеты не закрываются, пока игрок не завершит соединение (что означает, что соединение выполняется с одним сокетом для всего игрового процесса для каждого игрока), доска объект расширяет JComponent для игровой графики (показывает игровой процесс).

public void run()
{
    while(true)
    {
        //playerCount is fixed to 1 for testing
        for(int i=0; i<playerCount; i++)
        {
            try {
                //get every snake object from each player
                ObjectInputStream objectInputStream = new ObjectInputStream(clientSocket[i].getInputStream());
                snake[i] = (Snake)objectInputStream.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        for(int i=0; i<playerCount; i++)
        {
            try {
                Reader charInputStream = new InputStreamReader(clientSocket[i].getInputStream());
                dirInput = (char) charInputStream.read();

                //DO SOMETHING WITHOUT COMMUNICATION

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        for(int i=0; i<playerCount; i++)
        {
            try {
                OutputStream outputStream = clientSocket[i].getOutputStream();
                outputStream.write(i);

                ObjectOutputStream objectOutputStream = new ObjectOutputStream(clientSocket[i].getOutputStream());
                objectOutputStream.writeObject(snake);
                objectOutputStream.writeObject(apple);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Каждый Поток клиента Player (реализует Runnable) отправляет объект Snake mySnake 'и' переменная char inputControl 'на сервер и получает переменную int для playerNumber ', массив объектов Snake для board.snakes 'и' Appleобъект для board.apple 'с сервера.

public void run() {
    while(true)
    {
        try {
            Thread.sleep(50);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(gameSocket.getOutputStream());
            objectOutputStream.writeObject(mySnake);

            Writer charOutputWriter = new OutputStreamWriter(gameSocket.getOutputStream());
            charOutputWriter.write(inputControl);

            playerNumber = gameSocket.getInputStream().read();

            ObjectInputStream objectInputStream = new ObjectInputStream(gameSocket.getInputStream());
            board.snakes = (Snake[])objectInputStream.readObject();
            board.apple = (Apple)objectInputStream.readObject();
            mySnake = board.snakes[playerNumber];

            board.repaint();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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

Когда я отлаживал, поток игрового сервера зависал при чтении ввода символов (dirInput) из потока клиента, а поток клиента зависал при чтении ввода int (playerNumber) из потока игрового сервера.Видя, что оба потока застряли с InputStream, я подумал, что во время использования InputStream произошла тупиковая ситуация, поскольку оба потока пытаются использовать InputStream.Но я не уверен, действительно ли происходит тупик или нет.

Как я могу заставить оба потока общаться?Должен ли я использовать неблокирующую модель ввода / вывода для потока игрового сервера и потока клиента игрока?

1 Ответ

0 голосов
/ 13 мая 2019

Я не уверен, что ты на самом деле сделал! Но проблема в том, что вы создали ObjectInputStream много раз! Если вы хотите узнать, в чем проблема, просто создайте простой класс, который расширяет класс java.io.InputStream и создайте ObjectInputStream , поместив этот класс в качестве базового InputStream . Когда вы создадите класс ObjectInputStream , он попытается прочитать 4 байта как байты заголовка! Таким образом, это означает, что вы потеряли некоторые данные, и это причина, почему ваш поток застрял! Вы также можете проверить код ObjectInputStream, если у вас есть декомпилятор.

...