0

I'm pretty new to this whole "Sockets" and networking world.

First, I wanted to make a random chat program like "omegle" and it worked perfectly fine. I think I had some serious issues in the code, but it worked - so why bother? (I wish I did).

Now I am adding a "Multiplayer" option in my "Tic Tac Toe" game in android, it went wrong and I spent many hours figuring how to solve this problem but nothing worked, my app just kept crashing.

Here's the code for the simple chat program.

Server

public class server {
public static Map<Integer, MiniServer> clients;

public static void main(String args[]) throws IOException {
    clients = new HashMap<>();
    boolean listeningSocket = true;
    ServerSocket serverSocket = new ServerSocket(1234);
    while (listeningSocket) {
        Socket socket = serverSocket.accept();
        MiniServer mini = new MiniServer(socket);
        if (clients.isEmpty()) {
            clients.put(1, mini);
            mini.setId(1);
        } else {
            int i = 1;
            while (clients.containsKey(i))
                i++;
            clients.put(i, mini);
            mini.setId(i);
        }
        mini.start();
    }
    serverSocket.close();
}

Client

public class client {
private static String message;
private static boolean connected;
private static boolean connectedInternet;

public static void main(String args[]) throws UnknownHostException, IOException {
    Scanner textReader = new Scanner(System.in);
    Socket socket = new Socket("127.0.0.1", 1234);
    Scanner inputStreamReader = new Scanner(socket.getInputStream());
    connectedInternet = true;
    System.out.println("Hello Stranger, get ready to chat.");
    PrintStream printStream = new PrintStream(socket.getOutputStream());
    Thread getMessage = new Thread() {
        public void run() {
            while (true) {
                message = textReader.nextLine();
                if (!connected)
                    System.out.println("You are not connected to another Stranger yet, please wait.");
                else
                    printStream.println(message);
            }
        }
    };
    getMessage.start();
    while (connectedInternet) {
        String temp = inputStreamReader.nextLine();
        if (temp.equals("connected")) {
            connected = true;
            System.out.println("Found a Stranger, say hey !");
        } else if (connected) {
            if (temp.equals("!close")) {
                System.out.println("Stranger disconnected.");
                printStream.println("!new");
            } else
                System.out.println("Stranger: " + temp);
        }

    }
    textReader.close();
    socket.close();
    inputStreamReader.close();
}

MiniServer

public class MiniServer extends Thread {
private Socket socket = null;
public int id;
private boolean foundPlayer;
private int colleague;
private boolean connected;

public MiniServer(Socket socket) {
    super("MiniServer");
    this.socket = socket;
}

public void run() {
    Scanner inputStreamReader = null;
    String message;
    try {
        inputStreamReader = new Scanner(socket.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
    PrintStream p = null;
    try {
        p = new PrintStream(socket.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
    List<Integer> keys = new ArrayList<Integer>(server.clients.keySet());
    while (!foundPlayer) {
        for (Integer key : keys) {
            if (!server.clients.get(key).foundPlayer && key != id) {
                server.clients.get(key).foundPlayer = true;
                foundPlayer = true;
                server.clients.get(key).colleague = id;
                colleague = server.clients.get(key).id;
            }
        }
        try {
            keys = new ArrayList<Integer>(server.clients.keySet());
        } catch (ConcurrentModificationException e) {

        }
    }
    p.println("connected");
    connected = true;
    while (connected) {
        try {
            message = inputStreamReader.nextLine();
            if (message.equals("!new")) {
                foundPlayer = false;
                keys = new ArrayList<Integer>(server.clients.keySet());
                while (!foundPlayer) {
                    for (Integer key : keys) {
                        if (!server.clients.get(key).foundPlayer && key != id) {
                            server.clients.get(key).foundPlayer = true;
                            foundPlayer = true;
                            server.clients.get(key).colleague = id;
                            colleague = server.clients.get(key).id;
                        }
                    }
                    try {
                        keys = new ArrayList<Integer>(server.clients.keySet());
                    } catch (ConcurrentModificationException e) {

                    }
                }
                p.println("connected");
            } else
                sendToClient(message);
        } catch (NoSuchElementException e) {
            server.clients.remove(id);
            sendToClient("!close");
            closeSocket();
            connected = false;
        }
    }
}

public void setId(int i) {
    id = i;
}

public void sendToClient(String message) {
    Socket colleagueSocket = server.clients.get(colleague).socket;
    PrintStream rr = null;
    try {
        rr = new PrintStream(colleagueSocket.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
    rr.println(message);
}

public void closeSocket() {
    try {
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This program works great, but I'm pretty sure there are tons of problems with it.
Now here's my Server-side code for my android application.
Server

public class Server {
public static Map<Integer, MiniServer> clients;

public static void main(String args[]) throws IOException {
    clients = new HashMap<>();
    boolean listeningSocket = true;
    ServerSocket serverSocket = new ServerSocket(1234);
    while (listeningSocket) {
        Socket socket = serverSocket.accept();
        MiniServer mini = new MiniServer(socket);
        if (clients.isEmpty()) {
            clients.put(1, mini);
            mini.setId(1);
        } else {
            int i = 1;
            while (clients.containsKey(i))
                i++;
            clients.put(i, mini);
            mini.setId(i);
        }
        mini.start();
    }
    serverSocket.close();
}

Mini Server

public class MiniServer extends Thread {
private Socket socket;
private Socket colleagueSocket;
public int id;
private boolean foundPlayer;
private int colleague;
private boolean connected;
private String crossOrCircle;
private boolean thisGoes;
private Thread timeOut;
private PrintStream p;
private Timer timer;

public MiniServer(Socket socket) {
    super("MiniServer");
    this.socket = socket;
}

public void run() {
    Scanner inputStreamReader = null;
    String message;
    try {
        inputStreamReader = new Scanner(socket.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        p = new PrintStream(socket.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
    List<Integer> keys = new ArrayList<Integer>(Server.clients.keySet());
    while (!foundPlayer) {
        for (Integer key : keys) {
            if (!Server.clients.get(key).foundPlayer && key != id) {
                Server.clients.get(key).foundPlayer = true;
                foundPlayer = true;
                Server.clients.get(key).colleague = id;
                colleague = Server.clients.get(key).id;
                crossOrCircle = "X";
                Server.clients.get(key).crossOrCircle = "O";
                thisGoes = true;
                Server.clients.get(key).thisGoes = false;
                colleagueSocket=Server.clients.get(key).colleagueSocket;
                Server.clients.get(key).colleagueSocket=socket;
            }
        }
        try {
            keys = new ArrayList<Integer>(Server.clients.keySet());
        } catch (ConcurrentModificationException e) {

        }
    }
    p.println("connected");
    connected = true;
    p.println(crossOrCircle);
    while (connected) {
        try {
            message = inputStreamReader.nextLine();
            if (Character.toString(message.charAt(0)).equals(crossOrCircle) && thisGoes) {
                p.println(message);
                sendToClient(message);
                thisGoes = false;
                Server.clients.get(colleague).thisGoes = true;
            } else if (message.equals("!close")) {
                sendToClient("!closeClient");
                p.println("!closeClient");
                Server.clients.get(colleague).connected = false;
                connected = false;
                Server.clients.get(colleague).closeSocket();
                closeSocket();
                Server.clients.remove(colleague);
                Server.clients.remove(id);
            } else if (message.equals("!pause")) {
                timeOut = new Thread() {
                    @Override
                    public void run() {
                        timer = new Timer();
                        timer.schedule(
                                new TimerTask() {
                                    @Override
                                    public void run() {
                                        sendToClient("!closeClient");
                                        p.println("!closeClient");
                                        Server.clients.get(colleague).connected = false;
                                        connected = false;
                                        Server.clients.get(colleague).closeSocket();
                                        closeSocket();
                                        Server.clients.remove(colleague);
                                        Server.clients.remove(id);
                                    }
                                },
                                5000
                        );
                    }
                };
                timeOut.start();
            } else if (message.equals("!resume")) {
                timer.cancel();
            }
        } catch (NoSuchElementException e) {
            sendToClient("!closeClient");
            p.println("!closeClient");
            Server.clients.get(colleague).connected = false;
            connected = false;
            Server.clients.get(colleague).closeSocket();
            closeSocket();
            Server.clients.remove(colleague);
            Server.clients.remove(id);
        }
    }
}

public void setId(int i) {
    id = i;
}

public void sendToClient(String message) {
        PrintStream rr = null;
        try {
            rr = new PrintStream(colleagueSocket.getOutputStream());
        } catch (IOException | NullPointerException e) {
            e.printStackTrace();
        }
        rr.println(message);
    }
public void closeSocket() {
    try {
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public Socket getSocket(){
    return this.socket;
}

There's a problem in the sendClient() method, it keeps throwing NullPointerException.
What can I do? I'm not asking you to solve my problem.
Could you give me some advices please?
Thank you very much :)
Edit:
I forgot to mention some thing- I'm running the server on my computer and I'm using two different devices that are connected to the LAN.

java.lang.NullPointerException
    at com.ilya.rabinovich.tictactoe.MiniServer.sendToClient(MiniServer.java:134)
    at com.ilya.rabinovich.tictactoe.MiniServer.run(MiniServer.java:75)
Exception in thread "MiniServer" java.lang.NullPointerException
    at com.ilya.rabinovich.tictactoe.MiniServer.sendToClient(MiniServer.java:138)
    at com.ilya.rabinovich.tictactoe.MiniServer.run(MiniServer.java:75)

Edit 2:
I fixed this exception by changing this line

                    colleagueSocket=Server.clients.get(key).colleagueSocket;

To

                    colleagueSocket=Server.clients.get(key).socket;  

When running this app on the android emulators (android studio) it works perfectly fine, but when I try running this app on external devices (Lg g3 and nexus 7) it works really weird and crashes most of the times.
Edit 3:
Okay I solved the problem =)
The problem was in the client(runOnUiThread).
Anyways, do you think there are ways to improve my Server code? Thanks !

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
Ilya
  • 3
  • 2
  • 2
    Please post a full stack trace of the exception. We can't narrow it down without more details. – childofsoong Aug 19 '16 at 16:57
  • I've added a link to it in my post. – Ilya Aug 19 '16 at 17:44
  • 2
    Which line is line 134? – childofsoong Aug 19 '16 at 17:45
  • rr = new PrintStream(colleagueSocket.getOutputStream()); at the sendClient() method. – Ilya Aug 19 '16 at 19:12
  • If that's the line, then there's only one possibility - `colleagueSocket` is null, so you need to check where that's supposed to be coming from. – childofsoong Aug 19 '16 at 19:46
  • I'd recommend you rename the `server` class to follow Java naming conventions - it took me a while to realize that was a class whose static member you were accessing, rather than a class or method variable named `server` - if `Server` is unavailable due to a conflict, then perhaps a name such as `IlyaServer` would help. – childofsoong Aug 19 '16 at 19:50
  • I have finished working with the first program (3 first codes) long time ago. For some reason when I'm running the app on the android emulators (android studio) it works totally fine but when I'm running it on external devices it causes some problems and I have no idea how to solve them, the app is crashing. Sometimes it even works for few seconds. – Ilya Aug 20 '16 at 14:45
  • Since you changed your code, please post a new question with your changes and the new error. – Code-Apprentice Aug 23 '16 at 00:49

1 Answers1

0

I don't know if you already did, but you need to whitelist the server ip in your config.xml file. This might be one one reason.

  • I forgot to mention that I'm running the server on my computer, I'm using my LAN address. – Ilya Aug 19 '16 at 17:33