Alright, so I'm not sure if there really is an error or not.
I've created a listening server using Java and NetBeans, and am trying to get the protocol to work.
However, for some reason it doesn't want to accept incoming messages.
It will accept incoming connections and set up the object used for handling a client, but just wont receive any messages.
I'm not sure what's going on, am I doing something wrong? Also, I already have port 7777 port forwarded, and I'm doing testing using "127.0.0.1".
======================================================================
I currently have 3 classes:
The main class, GMServer:
public class GMServer {
public static void main(String[] args) throws IOException {
CreateListener createListener = new CreateListener("USA Server East",7777,500);
}
}
======================================================================
The CreateListener class:
public final class CreateListener {
private ServerSocket listenSocket = null;
private String serverName = "";
private int serverPort = 7777;
private int serverMax = 500;
private boolean terminate = false;
private double connectID = 0;
private String currentUser = "-1";
private listenParser[] connections;
private int listenArray = 0;
public listenParser[] users;
public int usercount;
private boolean listenerConnected = true;
public double getCID() {
this.connectID++;
return this.connectID;
}
public CreateListener(String sName, int sPort, int sMax) throws IOException {
//Set the server name, port, and max users.
this.serverName = sName; this.serverPort = sPort; this.serverMax = sMax;
//Try to create a listener socket.
try { this.listenSocket = new ServerSocket(this.serverPort); } //If not successful, output error and end program.
catch (IOException e) { System.err.println("Could not create a listening server on port "+this.serverPort); System.exit(7777); }
//Let the console know that the listening server was created successfully.
System.out.println("Creating Server: \""+serverName+"\" On Port "+serverPort+"...");
while(listenerConnected) {
try {
Socket accepted = this.listenSocket.accept();
new listenParser(accepted,getCID(),sMax).start();
} catch (IOException e) {
//Socket Wasn't Accepted?
}
}
//Close down server after anything should cause the constant loop to end.
listenSocket.close();
}
}
======================================================================
and then the listenParser class (where it should be handling all traffic from clients):
public class listenParser extends Thread {
public Socket[] global_sockets;
public int connections = 0;
private PrintWriter _out = null;
private BufferedReader _in = null;
private double cid = 0;
private Socket socket = null;
private String currentUser = "";
private int timeout = 0;
private boolean connectionOpen = true;
private int socketTimeout = 0;
private int socketTimeoutMax = 1000;
private String room = "";
private long x = 0;
private long y = 0;
public listenParser(Socket sock, double acID, int maxUsers) {
super("listenParser");
this.socket = sock;
System.out.println("Connected To A Client...");
}
public String readString(BufferedReader tmpBuffer) {
try {
return tmpBuffer.readLine();
} catch (IOException e) {
return "";
}
}
public String protocol(String arg) {
String RETURN = "";
switch(arg) {
case "login": currentUser = "1"; break;
case "echo": this._out.println(readString(this._in)); break;
default: /*Do Nothing*/ break;
}
//Only allow access to these commands if the user is logged in.
if (currentUser!="") {
switch(arg) {
default: break;
}
}
return RETURN;
}
public boolean good() {
if (this.currentUser.equals("")) {
return false;
}
return true;
}
#Override
public void run() {
try {
_out = new PrintWriter(socket.getOutputStream(),true);
_in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
connections++; if (connections>500) { connectionOpen = false; }
while(connectionOpen) {
try {
String arguments, reply;
arguments = this._in.readLine();
reply = protocol(arguments);
socketTimeout = 0;
} catch (IOException e) {
socketTimeout++;
if (socketTimeout>socketTimeoutMax) {
connectionOpen = false; break;
}
}
}
_out.close();
_in.close();
socket.close();
System.out.println("Client Disconnected...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
You are reading lines. Are you sending lines? Very common mistake. readLine() will block until it receives a newline, or EOS.
Speaking of EOS, the first thing you must do with the result of readLine() is check it for null, and if so close the socket and break out of the reading loop.
Related
I am trying to create for a university project a server / slave / client project.
The server should open 2 ports, one port will be for the connection of the slave and another port for the client.
I have setup 2 threads 1 for the client and another for the slave. The client should sent random numbers to server and server should forward randomly those numbers to slave instances. The slave should check if the current number exist on their list and if it's not available to store it, otherwise they should sent a message to server that the number already exist.
Then I created the client thread which consist of 2 threads, one for sending the numbers to server and another thread to read messages coming from the server.
There is something wrong with the code of the PrintWriter, I cannot make it to send the numbers to server when the code is inside the thread. If I move the code on the main and cancel the thread the messages are being sent without any issue.
What could be the issue for this?
Below is the current code from server (master) and the client.
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1";
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
Socket echoSocket = null;
BufferedReader in = null;
try {
echoSocket = new Socket(serverHostname, 18889);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Δεν μπορεί να πραγματοποιηθεί σύνδεση με τον σέρβερ: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + serverHostname);
System.exit(1);
}
ClientOut clientOut = new ClientOut(echoSocket);
clientOut.start();
ClientIn clientIn = new ClientIn(in);
clientIn.start();
in.close();
echoSocket.close();
}
public static class ClientOut extends Thread {
private PrintWriter out;
public ClientOut(Socket echoSocket) throws IOException {
this.out = new PrintWriter(echoSocket.getOutputStream(), true);
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
out.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
out.close();
}
}
public static class ClientIn extends Thread {
private BufferedReader in;
public ClientIn(BufferedReader in) {
this.in = in;
}
#Override
public void run() {
}
}
}
public class Master {
private int slavePort;
private int clientPort;
private SlaveThread slaveThread;
private ClientThread clientThread;
private boolean running = false;
public static int slaveConnected; // Slave connection counter
public Master(int slavePort, int clientPort) {
this.slavePort = slavePort;
this.clientPort = clientPort;
this.slaveConnected = 0;
public void startServer() {
try {
this.slaveThread = new SlaveThread(slavePort);
this.clientThread = new ClientThread(clientPort);
System.out.println( "Αναμονή για σύνδεση client / slave" );
slaveThread.start();
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopServer() {
running = false;
this.slaveThread.interrupt();
this.clientThread.interrupt();
}
class SlaveThread extends Thread {
private ServerSocket slaveSocket;
SlaveThread(int slavePort) throws IOException {
this.slaveSocket = new ServerSocket(slavePort);
}
#Override
public void run() {
running = true;
while (running) {
try {
// Call accept() to receive the next connection
Socket slSocket = slaveSocket.accept();
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Slave");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ClientThread extends Thread {
private ServerSocket clientSocket;
ClientThread(int clientPort) throws IOException {
this.clientSocket = new ServerSocket(clientPort);
}
#Override
public void run() {
running = true;
while (running) {
try {
Socket clSocket = clientSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clSocket.getInputStream()));
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Client");
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Client: " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Master server = new Master( 30091, 18889);
server.startServer();
// Automatically shutdown in 1 minute
try {
Thread.sleep( 60000 );
} catch(Exception e) {
e.printStackTrace();
}
server.stopServer();
}
I found the solution.
The Socket should be created on the Client Thread constructor and not to be passed as reference.
So the client should be
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1"; //Ορίζουμε την διεύθυνση που είναι ο σέρβερ
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
ClientOut clientOut = new ClientOut(serverHostname);
clientOut.start();
ClientIn clientIn = new ClientIn(serverHostname);
clientIn.start();
}
public static class ClientOut extends Thread {
private Socket echoSocket;
private PrintWriter writer;
ClientOut(String serverHostname) throws IOException {
this.echoSocket = new Socket(serverHostname, 18889);
this.writer = new PrintWriter(echoSocket.getOutputStream(), true);;
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
writer.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
writer.close();
}
}
I'm making a multithreaded FTP server in Java and I have a question about to go about handling multiple clients. Right now, I have a Server that looks like this:
public class Server {
private static final int HOST_PORT = 6000;
private ServerSocket serverSocket;
public Server(ServerModel serverModel) throws IOException {
serverSocket = new ServerSocket(HOST_PORT);
}
public void start() {
try {
acceptClients();
} catch (IOException e) {
e.printStackTrace();
}
}
private void acceptClients() throws IOException {
while (true) {
Socket client = serverSocket.accept();
ServerModel serverModel = new ServerModel();
Thread worker = new Thread(new ServerWorker(client, serverModel));
worker.start();
}
}
}
And a ServerWorker object which is responsible for interpreting client commands and responding to them:
public class ServerWorker implements Runnable {
private ServerRemoteHandler serverRemoteHandler;
private ServerModel serverModel;
private static final int GET_CODE = 1;
private static final int PUSH_CODE = 2;
private static final int CHANGE_DIRECTORY_CODE = 3;
private static final int PRINT_WORKING_DIRECTORY_CODE = 4;
private static final int FILE_EXISTS_CODE = 5;
private static final int LIST_FILES_DIRECTORIES_CODE = 6;
private static final int EXIT_CODE = 0;
public ServerWorker(Socket client, ServerModel serverModel) throws IOException {
this.serverModel = serverModel;
try {
serverRemoteHandler = new ServerRemoteHandler(client);
} catch (IOException e) {
e.printStackTrace();
}
}
private void parseCommand() {
int command;
try {
while (true) {
command = serverRemoteHandler.getCommand();
switch (command) {
case CHANGE_DIRECTORY_CODE:
changeDirectory();
break;
case PRINT_WORKING_DIRECTORY_CODE:
printWorkingDirectory();
break;
case FILE_EXISTS_CODE:
fileExists();
break;
case LIST_FILES_DIRECTORIES_CODE:
listFilesDirectories();
break;
case GET_CODE:
pushFile();
break;
case PUSH_CODE:
getFile();
break;
case EXIT_CODE:
exit();
break;
}
}
} catch (IOException e) {
exit();
}
}
private void printWorkingDirectory() throws IOException {
serverRemoteHandler.printWorkingDirectory(serverModel.getCurrentPath());
}
private void changeDirectory() throws IOException {
String fileName = serverRemoteHandler.getFileName();
boolean success = serverModel.changeDirectory(fileName);
serverRemoteHandler.changeDirectory(success);
}
private void fileExists() throws IOException {
String fileName = serverRemoteHandler.getFileName();
serverRemoteHandler.fileExists(serverModel.fileExists(fileName));
}
private void pushFile() throws IOException {
File file = serverModel.getFile(serverRemoteHandler.getFileName());
long fileSize = serverModel.getFileSize(file);
serverRemoteHandler.pushFile(file, fileSize);
}
private void listFilesDirectories() throws IOException {
serverRemoteHandler.listFilesDirectories(serverModel.listFilesDirectories());
}
private void getFile() throws IOException {
String fileName = serverRemoteHandler.getFileName();
File file = new File(serverModel.getCurrentPath() + File.separator + fileName);
serverRemoteHandler.getFile(file);
}
private void exit() {
serverRemoteHandler.exit();
}
#Override
public void run() {
while (true) {
parseCommand();
}
}
}
Each ServerWorker has an Object called RemoteHandler whose job is to send and receive information from the streams. My questions are regarding this line:
Thread worker = new Thread(new ServerWorker(client, serverModel));
Is this thread safe? Is this a good way of implementing it? Thank you.
Yes it is threadsafe. Everything in that line is method-local, so it is only accessible by the current thread, and then the worker thread starts while this one loops and gets a new set of values for these variables.
(That doesn't imply the entire program is thread-safe, of course.)
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
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 !
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 have a few questions about my server side code. Since i don't know how to debug the server side code i am asking it here what could be the reason. At my for(;;) loop if the if the msg comes null the for loop breaks before coming to my if(msg==null) statement so i can not broadcast it what might be the problem? Thanks
public class ChatServer {
String gonderen1;
String alan1;
private static final int PORT_NUMBER = 8000;
Map<String, List<PrintWriter>> clients;
List<PrintWriter> clientwriter;
ArrayList<String> liste = new ArrayList<String>();
/** Creates a new server. */
public ChatServer() {
clients = new HashMap<String, List<PrintWriter>>();
clientwriter = new LinkedList<PrintWriter>();
}
/** Starts the server. */
public void start() {
try {
ServerSocket s = new ServerSocket(PORT_NUMBER);
for (;;) {
Socket incoming = s.accept();
new ClientHandler(incoming).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/** Adds a new client identified by the given print writer. */
private void addClient(PrintWriter out,String alan) {
synchronized(clientwriter) {
clientwriter.add(out);
clients.put(alan, clientwriter);
}
}
/** Adds the client with given print writer. */
private void removeClient(PrintWriter out) {
synchronized(clientwriter) {
clientwriter.remove(out);
clients.remove(alan1);
}
}
private void broadcast(String msg,String alan) {
for(PrintWriter out : clients.get(alan)){
out.println(msg);
out.flush();
}
}
public static void main(String[] args) {
if (args.length > 0) {
System.out.println(USAGE);
System.exit(-1);
}
new ChatServer().start();
}
private class ClientHandler extends Thread {
private Socket incoming;
public ClientHandler(Socket incoming) {
this.incoming = incoming;
}
public void run() {
PrintWriter out = null;
try {
out = new PrintWriter(
new OutputStreamWriter(incoming.getOutputStream()));
// inform the server of this new client
/* ChatServer.this.addClient(out,"mert");
out.print("Welcome to AndyChat! mert");
out.println("Enter BYE to exit.");
out.flush();*/
BufferedReader in
= new BufferedReader(
new InputStreamReader(incoming.getInputStream()));
String msg;
for(;;) {
msg = in.readLine();
if(msg!=null){
liste.add(msg);
Pattern pat = Pattern.compile("<Gonderen>(.*?)</Gonderen>");
Matcher mat = pat.matcher(msg);
if (mat.find()) {
gonderen1 = mat.group(1).replaceAll("\\s",""); // => "3"
System.out.println("Gonderen "+gonderen1);
}
Pattern p = Pattern.compile("<Alan>(.*?)</Alan>");
Matcher m = p.matcher(msg);
if (m.find()) {
alan1 = m.group(1).replaceAll("\\s",""); // => "3"
out.print("dsa");
System.out.println("Alanin adi "+alan1);
}
if(alan1!=null){
System.out.println(clients.get("mert"));
ChatServer.this.addClient(out,alan1);
}
} else {
for(int i =0;i<liste.size();i++){
ChatServer.this.broadcast(msg,"mert");
System.out.println("null gelmedi");}
break;
}
}
incoming.close();
ChatServer.this.removeClient(out);
} catch (Exception e) {
if (out != null) {
ChatServer.this.removeClient(out);
}
e.printStackTrace();
}
}
}
}
Matcher mat = pat.matcher(msg); probably gives you NullPointerException if you pass to it a null msg.
You should move your if(msg==null) check to be before Matcher mat = pat.matcher(msg);.
pat.matcher(msg)
calls new Matcher (pat, msg)
which assigns this.text = msg (which is null) and then calls reset()
which calls to = getTextLength()
which returns text.length() // which is where the NullPointerException will be
// thrown
I have browsed, searched ... and nothing sparkles to my mind!
I am running a chat type service between a server and an Android app. The client connects, the server registers the socket, and every 10 minutes the server sends to all connected devices a message.
My problem is that randomly I have a connection reset exception. I can not trace back when the problem occurs.
My server side code is:
final public class ChatRoomService {
private final static String AUTHENTICATE = "AUTHENTICATE";
private final static String BROADCAST = "BROADCAST";
private final static String DISCONNECT = "DISCONNECT";
private final static String OK = "OK";
private final static String NOK = "NK";
private final static Logger LOGGER = Logger.getLogger(ChatRoomService.class);
private ServerSocket listener = null;
#Inject
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
#Inject
private PlayerManager playerManager;
PlayerManager getPlayerManager() {
return playerManager;
}
private static HashSet<ChatRoomConnection> connections = new HashSet<ChatRoomConnection>();
public void addConnection(ChatRoomConnection c) {
synchronized(connections) {
connections.add(c);
}
}
public void removeConnection(ChatRoomConnection c) {
synchronized(connections) {
connections.remove(c);
}
}
public void startListeningToChatRoomConnection() throws IOException {
listener = new ServerSocket(9010);
try {
LOGGER.infof("startListening - Start listening on port %s", 9010);
while (true) {
ChatRoomConnection connection = new ChatRoomConnection(listener.accept(), this);
addConnection(connection);
connection.start();
}
} catch (IOException e) {
if (!listener.isClosed())
LOGGER.errorf("listenToChatRoomConnection - Connection lost during connection: %s", e.getMessage());
} finally {
if (listener != null && !listener.isClosed()) {
LOGGER.infof("listenToChatRoomConnection - Stop listening");
listener.close();
}
}
}
public void stopListeningToChatRoomConnection() throws IOException {
if (!listener.isClosed()) {
LOGGER.infof("stopListeningToChatRoomConnection - Stop listening");
listener.close();
listener = null;
// Closing all sockets
for (ChatRoomConnection connection : connections) {
connection.close();
}
// Clear up the connections list
synchronized (connections) {
connections.clear();
}
}
}
public void broadcastToChatRoomClients(Object message) {
synchronized (connections) {
// Log
LOGGER.debugf("Broadcast ChatRoom: %s - %s",
connections.size(),
message.toString());
for (ChatRoomConnection connection : connections) {
LOGGER.debugf("Broadcast ChatRoom to %s", connection.userName);
connection.publish(message);
}
}
}
private ChatRoomService() {
}
private static class ChatRoomConnection extends Thread {
private Socket socket;
private BufferedReader readerFromClient;
private PrintWriter writerToClient;
public String userName;
private ChatRoomService chatCService;
ChatRoomConnection(Socket socket, ChatRoomService chatRoomService) {
super("ChatRoomConnection");
this.socket = socket;
this.chatRoomService = chatRoomService;
}
public void run() {
try {
readerFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writerToClient = new PrintWriter(socket.getOutputStream(), true);
// 1- Authenticate the Device/ Player
writerToClient.println(ChatRoomService.AUTHENTICATE);
writerToClient.flush();
Gson gson = new Gson();
Request request = gson.fromJson(readerFromClient.readLine(), Request.class);
if (chatRoomService.getPlayerManager().isPlayerSignedIn(request.getPlayerId(), request.getSignedInOn())) {
Player player = (Player) chatRoomService.getEntityManager().find(Player.class, request.getPlayerId());
userName = player.getUsername();
LOGGER.infof("listenToChatRoomConnection - Connection established with %s", userName);
writerToClient.println(ChatRoomService.OK);
writerToClient.flush();
while (true)
if ((readerFromClient.readLine() == null) ||
(readerFromClient.readLine().startsWith(ChatRoomService.DISCONNECT)))
break;
} else {
writerToClient.println(ChatRoomService.NOK);
writerToClient.flush();
}
} catch (Exception e) {
LOGGER.errorf("listenToChatRoomConnection - Error with %s: %s", userName, e.getMessage());
e.printStackTrace();
} finally {
try {
if (!socket.isClosed()) {
LOGGER.infof("listenToChatRoomConnection - Connection closed by the client for %s", userName);
socket.close();
}
} catch (IOException e) {
LOGGER.errorf("listenToChatRoomConnection - Can not close socket: %s", e.getMessage());
e.printStackTrace();
} finally {
chatRoomService.removeConnection(this);
}
}
}
public void publish(Object message) {
if (!socket.isClosed()) {
writerToClient.println(ChatRoomService.BROADCAST);
Gson gson = new Gson();
writerToClient.println(gson.toJson(message));
}
}
public void close() {
writerToClient.println(ChatRoomService.DISCONNECT);
try {
LOGGER.infof("listenToChatRoomConnection - Connection closed by the server for %s", userName);
socket.close();
} catch (IOException e) {
LOGGER.errorf("Error when trying to close a socket: %s", e.getMessage());
e.printStackTrace();
}
}
};
}
The device code is:
public class ServerBroadcastManager {
private static final String TAG = ServerBroadcastManager.class.getName();
// Type of messages from the server
static public String AUTHENTICATE = "AUTHENTICATE";
static public String DISCONNECT = "DISCONNECT";
static public String BROADCAST = "BROADCAST";
static public String OK = "OK";
static public String NOK = "NK";
private int networkPort;
private ServerBroadcastListener broadcastListener;
private Socket networkSocket;
BufferedReader in;
PrintWriter out;
public ServerBroadcastManager(Context context, ServerBroadcastListener listener, int port) {
this.networkPort = port;
this.broadcastListener = listener;
}
public void startListening(final Context context) {
Runnable run = new Runnable() {
#Override
public void run() {
// Make connection and initialize streams
try {
networkSocket = new Socket();
networkSocket.connect(new InetSocketAddress(mydomain, networkPort), 30*1000);
in = new BufferedReader(new InputStreamReader(
networkSocket.getInputStream()));
out = new PrintWriter(networkSocket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
if (line.startsWith(ServerBroadcastManager.AUTHENTICATE)) {
Request request = formatAuthenticateRequest(context);
Gson requestGson = new Gson();
out.println(requestGson.toJson(request));
out.flush();
// Waiting for confirmation back
line = in.readLine();
if (line.startsWith(ServerBroadcastManager.OK)) {
} else if (line.startsWith(ServerBroadcastManager.NOK)) {
}
} else if (line.startsWith(ServerBroadcastManager.BROADCAST)) {
Gson gson = new Gson();
#SuppressWarnings("unchecked")
LinkedHashMap<String,String> broadcast = gson.fromJson(in.readLine(), LinkedHashMap.class);
broadcastListener.processBroadcast(broadcast);
} else if (line.startsWith(ServerBroadcastManager.DISCONNECT)) {
break;
}
}
} catch (UnknownHostException e) {
Log.i(TAG, "Can not resolve hostname");
} catch (SocketTimeoutException e) {
Log.i(TAG, "Connection Timed-out");
broadcastListener.connectionFailed();
} catch (IOException e) {
Log.i(TAG, "Connection raised on exception: " + e.getMessage());
if (!networkSocket.isClosed()) {
broadcastListener.connectionLost();
}
}
}
};
Thread thread = new Thread(run);
thread.start();
}
public void stopListening() {
try {
if (networkSocket != null)
networkSocket.close();
} catch (IOException e) {
Log.i(TAG, "Exception in stopListening: " + e.getMessage());
}
}
private Request formatAuthenticateRequest(Context context) {
Request request = new Request();
SharedPreferences settings = context.getApplicationContext().getSharedPreferences(Constants.USER_DETAILS, 0);
request.setPlayerId(BigInteger.valueOf((settings.getLong(Constants.USER_DETAILS_PLAYERID, 0))));
request.setSignedInOn(settings.getLong(Constants.USER_DETAILS_SIGNEDINON, 0));
return request;
}
}
My last resort might be to move my server to another location, and see if this could not be related to my broadband router. I have notice that some of my HTTP call do not reach the server as well, though port forwarding is properly in place.
Thanks.
David.
I can't find where in your source code the server sends a message every 10 minutes to all connected clients, but I have experienced connection reset exceptions while using long-lasting WebSocket connections. I solved that problem by making sure some data (ping-pong message) was send from the client every minute.
At the time I traced the problem to my home-router which simply closed all idle connections after 5 minutes, but firewalls can exhibit the same kind of behavior. Neither server or client will notice a closed connection until data is transmitted. This is especially nasty for the client if the client is expecting data from the server - that data will simply never arrive. Therefor, make it the responsibility of the client to check if a connection is still valid (and reconnect when needed).
Since the introduction of the ping-pong message from the client every minute, I have not seen connection reset exceptions.