0
votes

I am trying to build a multiplayer game with game server operating with at most 4 clients, using java Socket and ServerSocket. I limited number of clients to 1 in this code for testing, and used Blocking I/O Model for both player and server.

Game Server Thread (implements Runnable) receives 'Snake object to snake[i]' and 'char variable to dirInput' from each client using socket input stream, and sends 'Snake object Array snake' and 'Apple object apple' using socket output stream. Both Snake object and Apple object is Serializable.

In here, clientSocket array consists all connected client Sockets, and these sockets don't close until player ends connection (which means connection is done with one socket for entire gameplay for each player). board object extends JComponent for Game Graphics (shows gameplay).

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();
            }
        }
    }
}

Each Player Client Thread (implements Runnable) sends 'Snake object mySnake' and 'char variable inputControl' to server and receives 'int variable to playerNumber', 'Snake object Array to board.snakes' and 'Apple object to board.apple' from server.

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();
        }
    }
}

The problem is, when I start both game server and client and try to communicate, both Game Server Thread and Player Client Thread stucks while communicating.

When I debugged, Game Server Thread is stuck with reading char input (dirInput) from Client Thread, and Client Thread is stuck with reading int input (playerNumber) from Game Server Thread. By seeing both thread are stuck with InputStream, I thought deadlock happened while using InputStream, since both thread tries to use InputStream. But I'm not sure if deadlock is really happening or not.

How can I make both thread communicate? Should I use Nonblocking I/O model for both Game Server Thread and Player Client Thread?

1
You should create the object streams once per socket, not every time you want to read or write something, and always create the object output before the object input. - user207421
@user207421 I thought wrapper class like object stream 'share' one inputStream for one socket, so that it is ok to make as many wrapper stream class as possible. Am I thinking wrong? - piecemaker
NB (1) Your sleep is just literally a waste of time; (2) don't do I/O other than via the object streams. - user207421
@user207421 Thank you for your comment. I fixed my code everywhere according to your suggestion, but my program stucks in the same place as before. Is this due to deadlock on inputStream between server thread and client thread? - piecemaker
You must create the object output steam before the object input stream, at both ends. - user207421

1 Answers

0
votes

I am not sure what you did really ! But the problem is that you created ObjectInputStream many times! If you want to know what is the problem just create a simple class that extends the java.io.InputStream class and make a ObjectInputStream by put this class as base InputStream. You will see when a ObjectInputStream class create , it will try to read 4 bytes as header bytes! So it means you lost some data , and it's the cause why your thread stuck ! You can check code of ObjectInputStream too if you have a decompiler.