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 !