How to use Java Socket with Runnable - java

I want to call a function cycle() that do something for every some x second.
At this time i can call it only when it has a request from client.
public class ChatServer implements Runnable {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
cycle();
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
out.println("NAMEACCEPTED");
writers.add(out);
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Yeah, code below is work when i remove Handle class from my code.
My problem is i can't combine them together, please help or suggest. Many thanks.
private void cycle() {
//do something
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
beforeTime = System.currentTimeMillis();
}
}

Do you try to start a separate thread for the cycle function before call listen to the socket.
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
//start separate thread to keep loop....
new Thread(new ChatServer()).start();
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}

Related

Cannot invoke "java.net.ServerSocket.close()" because "Server.server" is null

I'm trying to write a simple client/server application. I have a data on a client's side, that turns into an integer array and transfers to server. The server makes the calcutaions and returns them to client. But my program falls with this exception.
Sorry for long text, I'm just studying and really need your help.
public class Client {
private static Socket clientSocket;
private static ObjectInputStream in;
private static ObjectOutputStream out;
private static int[] parsedValue;
public Client(String input) {
try {
parsedValue = Arrays.stream(input.split(",")).mapToInt(Integer::parseInt).toArray();
} catch (Exception e) {
e.printStackTrace();
}
}
public Client(int[] input) {
parsedValue = input;
}
public Client(List<Integer> input) {
try {
parsedValue = input.stream().mapToInt(d->d).toArray();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
try {
clientSocket = new Socket("localhost", 4004);
in = new ObjectInputStream(clientSocket.getInputStream());
out = new ObjectOutputStream(clientSocket.getOutputStream());
String clientTestString = "440,5,16";
Client stringClient = new Client(clientTestString);
out.writeObject(stringClient.parsedValue);
out.flush();
System.out.println(in.readObject());
int[] clientIntsTest = {39, 10, 5};
Client arrayClient = new Client(clientIntsTest);
out.writeObject(arrayClient.parsedValue);
out.flush();
System.out.println(in.readObject());
List<Integer> clientsTestList = Arrays.asList(781, 9, 7);
Client listClient = new Client(clientsTestList);
out.writeObject(listClient.parsedValue);
out.flush();
System.out.println(in.readObject());
} finally {
System.out.println("Client was closed");
clientSocket.close();
in.close();
out.close();
}
} catch (IOException | ClassNotFoundException e) {
System.err.println(e);
}
}
}
public class Server {
private static Socket clientSocket;
private static ServerSocket server;
private static ObjectInputStream in;
private static ObjectOutputStream out;
private static int[] parsedValue;
public String getResult() {
return calculation(parsedValue);
}
public String calculation(int[] parsedValue) {
parsedValue[0] = toDecimal(parsedValue[0], parsedValue[1]);
String answer = "";
int temp = 0;
String digits = new String("ABCDEF");
while (parsedValue[0] > 0) {
temp = parsedValue[0] % parsedValue[2];
if (temp < 10) {
answer = temp + answer;
} else {
answer = digits.charAt(temp - 10) + answer;
}
parsedValue[0] /= parsedValue[2];
}
return answer;
}
public int toDecimal(int value, int baseNotation) {
int i = 0;
int decimalNumber = 0;
if (value > 0) {
while (value != 0) {
decimalNumber += (value % 10) * Math.pow(baseNotation, i);
value /= 10;
i++;
}
}
return decimalNumber;
}
public static void main(String[] args) {
try {
try {
server = new ServerSocket(4004);
System.out.println("Server runs");
clientSocket = server.accept();
try {
in = new ObjectInputStream(clientSocket.getInputStream());
out = new ObjectOutputStream(clientSocket.getOutputStream());
parsedValue = (int[]) in.readObject();
System.out.println(parsedValue);
Server examp = new Server();
String answer = examp.getResult();
System.out.println(answer);
out.writeObject(answer);
out.flush();
} finally {
clientSocket.close();
in.close();
out.close();
}
} finally {
System.out.println("Server closed");
server.close();
}
} catch (IOException | ClassNotFoundException e) {
System.err.println(e);
}
}
}
In this two lines
Server examp = new Server();
String answer = examp.getResult();
you cretat a new object which overriddes the field private static ServerSocket server;
A better solution is to put the logic from your main() into a seperate method like run(), instantiate in main() a new object of server and call the run() on it. Dont't forget to make all fields as instance members by removing the static keyword.
public static void main(String[] args) {
Server examp = new Server();
examp.run();
}
public void run() {
try {
try {
server = new ServerSocket(4004);
System.out.println("Server runs");
clientSocket = server.accept();
try {
in = new ObjectInputStream(clientSocket.getInputStream());
out = new ObjectOutputStream(clientSocket.getOutputStream());
parsedValue = (int[]) in.readObject();
System.out.println(parsedValue);
String answer = getResult();
System.out.println(answer);
out.writeObject(answer);
out.flush();
} finally {
clientSocket.close();
in.close();
out.close();
}
} finally {
System.out.println("Server closed");
server.close();
}
} catch (IOException | ClassNotFoundException e) {
System.err.println(e);
}
}
By the way: You should always use this patern to get out of the 'static-trap'. So I suggest you refactor your Client calss too.

Multithread Server and Client with sockets in Java

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

Synchronized method() running only 1 thread till end from a poll of several

This is a project I'm trying to do for University.
I'm making an app using sockets to connect several Clients to a Server.
When I get a new connection a new instance of ServerHandler is called that listens to the port for requests from the Client.
This is my ServerHandler class
public class ServerHandler implements Runnable {
private Socket clientSocket;
private Server server;
ArrayList<Thread> threads = new ArrayList<Thread>();
ArrayList<News> news = new ArrayList<News>();
ArrayList<News> filteredNews = new ArrayList<>();
private int iterator = 0;
private boolean available = true;
private boolean finished = false;
public ServerHandler(Socket clientSocket, Server server) {
this.clientSocket = clientSocket;
this.server = server;
this.news = server.getListNews();
}
#Override
public void run() {
System.out.println("Hello!");
while(true) {
try {
System.out.println("Waiting for input");
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String str = br.readLine();
System.out.println(str);
new Thread(new Runnable() {
#Override
public void run() {
try {
manageMessages();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void manageMessages() throws IOException, InterruptedException {
System.out.println("Button Search.");
launchThreads(str);
for(Thread t : threads) {
t.join();
}
filteredNews.sort(null);
System.out.println("News have been filtered and sorted.");
System.out.println("Sending info to Client.");
sendtoClient();
System.out.println("Sent info to Client.");
}
}).start();
} catch (IOException e) {
System.out.println("Socket closed" + e);
break;
}
}
}
When I get a request I launch a new Thread responsible of returning something to the Client.
My problem comes from the launchThreads(String str) method.
This method is meant to create and add 10 threads to an Array of Threads.
Each Thread then is going to run through the same ArrayList of News in search of a word (String str, sent by the Client).
All threads are supposed to share the work, that is searching for the String str through every single News in the shared ArrayList<News>.
private void launchThreads(String str) {
System.out.println("Lauching threads");
filteredNews.clear();
threads.clear();
finished = false;
available = true;
iterator = 0;
for(int i = 0; i < 10; i++) {
threads.add(new Thread(new Runnable(){public void run(){try {
queueThreads(str);
filterNews(str);
} catch (InterruptedException e) {
e.printStackTrace();
}}}));
threads.get(i).start();
}
System.out.println("Launched threads: " + threads.size());
}
private synchronized void queueThreads(String str) throws InterruptedException {
while(!available && !finished) {
System.out.println("Waiting.");
wait();
}
System.out.println("Gone through.");
available = false;
}
private synchronized void filterNews(String str) throws InterruptedException {
int contador = 0;
if(iterator < news.size()) {
String temp = news.get(iterator).getTitle() + " " + news.get(iterator).getBody();
String[] tempArray = temp.replaceAll("[^a-zA-Z ]", "").split("\\s+");
for(String word : tempArray) {
if(word.equalsIgnoreCase(str)) {
contador++;
}
}
if(contador > 0) {
News n = new News(news.get(iterator).getTitle(),news.get(iterator).getBody(), contador);
n.setTitle(contador + " - " + n.getTitle());
System.out.println(news.get(iterator).toString());
filteredNews.add(n);
}
iterator++;
}else {
finished = true;
}
available = true;
notifyAll();
queueThreads(str);}
What I'm getting is that only 1 Thread runs the whole search while the other ones just stay waiting until I change the finished flag to 'true', that is set when the search ends.
I would love to get some help on how can I launch several threads to run through the array sharing work between them.
Thanks in advance.

Why isn't my client socket inputstream receiving message sent from server socket outputstream

This is the SocketServer code that generates a server thread
public class ProcessorCorresponder {
protected final static Logger logger = LogManager.getLogger( ProcessorCorresponder.class );
private static int port = Integer.parseInt(PropertiesLoader.getProperty("appserver.port") == null ? "666" : PropertiesLoader.getProperty("appserver.port"));
private static int maxConnections = Integer.parseInt(PropertiesLoader.getProperty("appserver.maxconnections") == null ? "666" : PropertiesLoader.getProperty("appserver.maxconnections"));
public static void main(String[] args) {
logger.info("Starting server .. "
+ "[port->" + port
+ ",databaseName->" + databaseName + "]");
try (ServerSocket listener = new ServerSocket();) {
listener.setReuseAddress(true);
listener.bind(new InetSocketAddress(port));
Socket server;
int i = 0;
while((i++ < maxConnections) || (maxConnections == 0)) {
server = listener.accept();
logger.debug(
"New Thread listening on " + server.getLocalAddress().toString() + ":" + server.getLocalPort()
+ ", initiated from IP => " + server.getInetAddress().toString() + ":" + server.getPort()
);
MySocketServer socSrv = new MySocketServer (server);
Thread t = new Thread( socSrv );
t.start();
}
} catch (Exception ex) {
logger.error("Error in ProcessorInterface", ex);
}
}
}
Server code: This is a thread to handle one connection, there is a program that monitors a serversocket and spins off request threads as needed.
public class MySocketServer implements Runnable {
protected final static Logger logger = LogManager.getLogger(MySocketServer.class);
private final Socket server;
// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;
private StringBuffer buffHeartbeatMessage = new StringBuffer().append((char) 0).append((char) 0).append((char) 0)
.append((char) 0).append((char) 0).append((char) 0);
private Heartbeat heartbeat = new Heartbeat(/* 60 */3000, buffHeartbeatMessage.toString());
public MySocketServer(Socket server) {
this.server = server;
}
#Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(this.server.getInputStream()));
BufferedOutputStream out = new HeartbeatBufferedOutputStream(this.server.getOutputStream(),
heartbeat)) {
final StreamListener listener = new StreamListener(in);
listener.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getID() == ActionEvent.ACTION_PERFORMED) {
if (event.getActionCommand().equals(StreamListener.ERROR)) {
logger.error("Problem listening to stream.");
listener.setShouldContinue(false);
stopRunning();
} else {
String messageIn = event.getActionCommand();
if (messageIn == null) { // End of Stream;
stopRunning();
} else { // hey, we can do what we were meant for
logger.debug("Request received from client");
// doing stuff here
...
// done doing stuff
logger.debug("Sending Client Response");
try {
sendResponse(opResponse, out);
} catch (Exception ex) {
logger.error("Error sending response to OP.", ex);
}
}
}
}
}
});
listener.start();
while (shouldContinue) {
// loop here until shouldContinue = false;
// this should be set to false in the ActionListener above
}
heartbeat.setShouldStop(true);
return;
} catch (Exception ex) {
logger.error("Error in ESPSocketServer", ex);
return;
}
}
private void stopRunning() {
shouldContinue = false;
}
private void sendResponse(ClientResponse opResponse, BufferedOutputStream out) throws Exception {
logger.debug("Before write");
out.write(opResponse.getResponse().getBytes());
logger.debug("After write. Before flush");
out.flush();
logger.debug("After flush");
// this log message is in my logs, so I know the message was sent
}
}
My StreamListener class.
public class StreamListener extends Thread {
protected final static Logger logger = LogManager.getLogger(StreamListener.class);
public final static String ERROR = "ERROR";
private BufferedReader reader = null;
private List<ActionListener> actionListeners = new ArrayList<>();
private boolean shouldContinue = true;
public StreamListener(BufferedReader reader) {
this.reader = reader;
}
#Override
public void run() {
while (shouldContinue) {
String message;
try {
// client blocks here and never receives message
message = reader.readLine();
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, message);
fireActionPerformed(event);
} catch (IOException e) {
e.printStackTrace();
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ERROR);
fireActionPerformed(event);
}
}
}
public void setShouldContinue(boolean shouldContinue) {
this.shouldContinue = shouldContinue;
}
public boolean getShouldContinue() {
return shouldContinue;
}
public boolean addActionListener(ActionListener listener) {
return actionListeners.add(listener);
}
public boolean removeActionListener(ActionListener listener) {
return actionListeners.remove(listener);
}
private void fireActionPerformed(ActionEvent event) {
for (ActionListener listener : actionListeners) {
listener.actionPerformed(event);
}
}
}
My Heartbeat class
public class Heartbeat extends Thread {
private BufferedOutputStream bos = null;
private int beatDelayMS = 0;
private String message = null;
private boolean shouldStop = false;
public Heartbeat(int beatDelayMS, String message) {
this.beatDelayMS = beatDelayMS;
this.message = message;
setDaemon(true);
}
#Override
public void run() {
if (bos == null) { return; }
while(!shouldStop) {
try {
sleep(beatDelayMS);
try {
bos.write(message.getBytes());
bos.flush();
} catch (IOException ex) {
// fall thru
}
} catch (InterruptedException ex) {
if (shouldStop) {
return;
}
}
}
}
public void setBufferedOutputStream(BufferedOutputStream bos) {
this.bos = bos;
}
public BufferedOutputStream getBufferedOutputStream() {
return bos;
}
public void setShouldStop(boolean shouldStop) {
this.shouldStop = shouldStop;
}
public boolean getShouldStop() {
return shouldStop;
}
}
My HeartbeatBufferedOutputStream
public class HeartbeatBufferedOutputStream extends BufferedOutputStream {
private Heartbeat heartbeat = null;
public HeartbeatBufferedOutputStream(OutputStream out, Heartbeat heartbeat) {
super(out);
this.heartbeat = heartbeat;
this.heartbeat.setBufferedOutputStream(this);
heartbeat.start();
}
#Override
public synchronized void flush() throws IOException {
super.flush();
heartbeat.interrupt();
}
}
And finally here is the "Client" class
public class Mockup extends Thread {
protected final static Logger logger = LogManager.getLogger(Mockup.class);
// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;
public static void main(String[] args) {
new Mockup().start();
}
#Override
public void run() {
try (Socket socket = new Socket("localhost", 16100);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
final StreamListener listener = new StreamListener(in);
listener.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getID() == ActionEvent.ACTION_PERFORMED) {
if (event.getActionCommand().equals(StreamListener.ERROR)) {
logger.error("Problem listening to stream.");
listener.setShouldContinue(false);
stopRunning();
} else {
String messageIn = event.getActionCommand();
if (messageIn == null) { // End of Stream;
stopRunning();
} else { // hey, we can do what we were meant for
// convert the messageIn to an OrderPower request, this parses the information
logger.info("Received message from server. [" + messageIn + "].");
}
}
}
}
});
listener.start();
StringBuffer buff = new StringBuffer("Some message to send to server");
logger.info("Sending message to server [" + buff.toString() + "]");
out.write(buff.toString().getBytes());
out.flush();
boolean started = false;
while (shouldContinue) {
if (!started) {
logger.debug("In loop");
started = true;
}
// loop here until shouldContinue = false;
// this should be set to false in the ActionListener above
}
logger.info("Exiting Mockup");
return;
} catch (Exception ex) {
logger.error("Error running MockupRunner", ex);
}
}
private void stopRunning() {
shouldContinue = false;
}
}
I have confirmed from logging messages that the Server sends a message to the BufferedOutputStream, and is flushed, but the Client logs indicate that it is blocked on the reader.readLine() and never gets the message.
You are reading lines but you are never writing lines. Add a line terminator to what you send.

Made a code for a simple chat and it worked, made similar thing in android studio and it didn't work, what's wrong? [duplicate]

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.

Categories

Resources