-1

Hi all :) Sorry for this really long question but this needs some explaination.

I was given an assignment where i have to turn a very simple game into a 2 player multiplayer game. The reason why we have to make this game is to learn more about threads and concurrency. I have never worked with concurrency nor with multiple threads.

My idea is to create a TCP server like i have done in GameServer.java where i create a new ServiceObject for each player. I create a thread for each ServiceObject where i will recieve, handle and send commands from a client.

Gameserver.java

package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class GameServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(6789);
        System.out.println("Waiting for clients to connect . . . ");

        Socket s1 = server.accept();
        System.out.println("Clients connected.");
        PlayerService servicep1 = new PlayerService(s1);
        Thread t1 = new Thread(servicep1);
        Socket s2 = server.accept();
        System.out.println("Clients connected.");
        PlayerService servicep2 = new PlayerService(s2);
        Thread t2 = new Thread(servicep2);
        t1.start();
        t2.start();
        servicep1.sendDataToClient("ready");
        servicep2.sendDataToClient("ready");
    }
}

PlayerService.java

package server;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;

import game2016.Player;

public class PlayerService extends Thread {
    private Socket s;
    private PlayerService opponent;
    private Scanner in;
    private PrintWriter out;


    public PlayerService(Socket aSocket) {
        this.s = aSocket;
    }

    public void setOpponent(PlayerService opponent) {
        this.opponent = opponent;
    }

    public void run() {
        try {
            in = new Scanner(s.getInputStream());
            out = new PrintWriter(s.getOutputStream());
            try {
                doService();
            } finally {
//              s.close();
            }
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }

    public void doService() throws IOException {
        while (true) {
            if (!in.hasNext()) {
                return;
            }
            String command = in.next();
            if (command.equals("QUIT")) {
                return;
            } else
                recieveFromClient(command);
        }
    }

    public void recieveFromClient(String command) throws IOException {
        System.out.println(command);
        if(command.equals("player")) {
            String newPlayerName = in.next();
            int xPos = in.nextInt();
            int yPos = in.nextInt();
            String direction = in.next();
//          sendDataToOpponent("addOpponent " + newPlayerName + " " + xPos + " " +  yPos + " " + direction);
        } 
    }

    public void sendDataToClient(String response) {
        out.write(response + "\n");
        out.flush();
    }

    public void sendDataToOpponent(String response) {
        opponent.sendDataToClient(response);
    }

    }

To send data from one client to another client i have a reference to the opponents servicelayer as i can invoke the sendDataToOpponent() method to send data to him and if the server have to communicate i can just invoke sendDataToClient() from the server.

My problem is that i want to postpone opening my clients GUI to both clients have connected.

Main.java(Client) - GUI code have been left out

private static Socket s;
private static InputStream instream;
private static OutputStream outstream;
private static Scanner in;
private static PrintWriter out;
private static boolean isOpponentConnected;

public static void main(String[] args) throws Exception {
    openConnection();
    reciever();
    waitOpponentConected();
    launch(args);
}

public static void waitOpponentConected() throws Exception {
    while(!isOpponentConnected) {
        System.out.println("Waiting for opponent");
        Thread.sleep(2000);
    }
    System.out.println("Opponent is ready now");
}

public static void openConnection() throws IOException {
    s = new Socket("localhost", 6789);
    System.out.println("Connection established");

    instream = s.getInputStream();
    outstream = s.getOutputStream();
    in = new Scanner(instream);
    out = new PrintWriter(outstream);
}

public static void responseFromServer() throws IOException {
     try {
         while(in.hasNext()) {
                String response = in.next();
                if(response.equals("ready")) {
                    isOpponentConnected = true;
                    System.out.println("Ready");
                } 
         }
        } catch (Exception e) {
        }
 }

public static void reciever() {
    Task<Void> task = new Task<Void>() {

        @Override
        protected Void call() throws Exception {
            while(true) {
                responseFromServer();
            }
        }

    };
    new Thread(task).start();
}

public static void sendCommandToServer(String command) throws IOException {
    out.print(command + "\n");
    out.flush();
}

I've created a Thread to recieve commands from the server, and when both clients have connected to the server it sends a string 'ready' to each of the clients. My thought was that The Main-thread sleeps till isOpponentConnected is true.

But my gameserver fails and prints out a nullpointer exception when the second clients connects to the server. I've spend to days reading and trying to fix this bug. When i run the code in debug mode, both clients recieves the ready signal and the GUI starts for both clients.

Exception in thread "main" java.lang.NullPointerException
    at server.PlayerService.sendDataToClient(PlayerService.java:67)
    at server.GameServer.main(GameServer.java:23)

Can you guys see anything i'm obviously doing wrong?

I think this queston is interesseting because it's not just the nullpointerexception, it's about structering TCP server-client relationships and the chain when things are initialized and ready when threads and connections are made.

1 Answers1

0

It should be fixable from inside the PlayerService.java class you have posted.
I suggest moving:

in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());

from public void run() to your PlayerService constructor:public PlayerService(Socket aSocket)
It looks like the function sendDataToClient is trying to use the out variable before it gets initialised.

Paul Karam
  • 4,052
  • 8
  • 30
  • 53
  • It works now. So the Main thread of GameServer runs the sendDataToClient before the threads have started properly? – Mikkel Andersen Oct 14 '16 at 07:33
  • @MikkelAndersen Threads are usually called Light Weight processes, so they share a fraction of time to run one after the other. As for example, go create two threads, and make each one loop for 100 times printing which iteration it is at, in rare occasions you would find the same result. In your example, you have created the instance, but didn't directly start the thread, so main thread was faster from your newly created thread and continued executing before initialising the input and output variables. You could have started your PlayerService thread directly as well, but I am not totally sure – Paul Karam Oct 14 '16 at 07:44