Sending data to queue not functioning - java

I have socket connection which keep reading data and then it will send it via a queue for next processing in another thread. I notice at times it just stop sending data to the queue. I will print this System.out.println("\n\nSending TO QUEUE : "+message); and stop but I do not see any error being capture any method to capture the errors? What could also be the possible error here?
class ConnectionHandler implements Runnable {
private Socket receivedSocketConn1;
ConnectionHandler(Socket receivedSocketConn1) {
this.receivedSocketConn1=receivedSocketConn1;
}
public void run() {
BufferedWriter w = null;
BufferedReader r = null;
String message="";
try {
PrintStream out = System.out;
BufferedWriter fout = null;
w = new BufferedWriter(new OutputStreamWriter(receivedSocketConn1.getOutputStream()));
r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
int m = 0, count=0;
int nextChar=0;
System.out.println( "\n\n\n THE device"+" "+ receivedSocketConn1.getInetAddress() +":"+receivedSocketConn1.getPort()+" IS CONNECTED ");
while ((nextChar=r.read()) != -1)
{
message += (char) nextChar;
int i = message.indexOf("GET");
if(i != -1) {
break;
}
if (nextChar == '#')
{
w.flush();
System.out.println("\n\nSending TO QUEUE : "+message);
databaseQueue.add(message);
System.out.println("\n\nSent TO QUEUE : "+message);
message="";
}
}
System.out.println( "\n\n\n THE device close connection"+" "+ receivedSocketConn1.getInetAddress() +":"+receivedSocketConn1.getPort()+" IS CONNECTED ");
}
catch (Exception ex)
{
ex.printStackTrace(System.out);
}
finally
{
try
{
if ( w != null )
{
w.close();
}
}
catch(IOException ex){
ex.printStackTrace(System.out);
}
}
}
}
Database processing queue thread snippet code.
class DatabaseProcessor implements Runnable {
// updates databaase with data queued by ConnectionHandler
Connection dbconn = null;
Statement stmt = null;
Statement stmt1 = null;
Statement stmt2 = null;
Date connCreated = null;
public void run()
{
// this is just like the QueueProcessor example I gave you
// open database connection
createConnection();
while (true)
{
try
{
int count=0;
String message = "";
message = databaseQueue.take();
System.out.println("\n\nPICKED AT QUEUE : "+message);
if (message.equals(null)) {
System.out.println("QueueProcessor is shutting down");
break; // exit while loop, ends run() method
}
//there is more codes but is too long to be put here.
}
}
}
}

I edited the code from your example a bit (simplied and removed stuff for testing) and I get the following output:
Client (telnet):
telnet localhost 7777
Trying ::1...
Connected to localhost.
Escape character is '^]'.
peter
test
Server:
PICKED AT QUEUE : peter
PICKED AT QUEUE : test
Code:
public class Trash {
private final static LinkedBlockingQueue<String> databaseQueue = new LinkedBlockingQueue<String>();
public static void main(String[] args) {
new Thread(new DatabaseProcessor()).start();
try {
ServerSocket serverSocket = new ServerSocket(7777);
Socket socket = serverSocket.accept();
new Thread(new ConnectionHandler(socket)).start();
Thread.sleep(10000000);
} catch (Exception e) {
e.printStackTrace();
}
}
static class ConnectionHandler implements Runnable {
private Socket receivedSocketConn1;
ConnectionHandler(Socket receivedSocketConn1) {
this.receivedSocketConn1 = receivedSocketConn1;
}
public void run() {
try {
BufferedReader r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
String message = "";
while (message == null || !message.equals("") || !message.equalsIgnoreCase("quit")) {
message = r.readLine();
if (message == null) {
continue;
}
databaseQueue.add(message);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
static class DatabaseProcessor implements Runnable {
public void run() {
while (true) {
try {
String message = "";
message = databaseQueue.take();
System.out.println("\n\nPICKED AT QUEUE : " + message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

Related

Java - Multithread Server to serve multiple concurrent clients

I've been trying to make the code below to have multiple clients communicate with the same server.
Currently, it works one client at a time with the server but it seems to be that when the second client opens, code stops at new ObjectInputStream(connection.getInputStream()); in the Class 3 (client) - see below.
I've tried making the inputstream object transient to be shared in different threads but it didn't work, nor with making runClient method synchronized.
If I were to implement Serializable in the client class using serialVersionUID, how can I make multithreading work with the same server or is there any better way..?
Class 1 - server main
public class EchoServer {
private ServerSocket server;
private int portNum;
public static final int DEFAULT_PORT = 8081;
public EchoServer(int portNum) {
this.portNum = portNum;
}
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length > 0) {
(new EchoServer(Integer.parseInt(args[0]))).runServer();
} else {
(new EchoServer(DEFAULT_PORT)).runServer();
}
}
}
Class 2
public class ClientHandler implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
/** Integer to hold the message number. */
private int messagenum;
private Socket connection;
public ClientHandler(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
do{
handleRequest();
} while (true);
}
public void handleRequest() {
try {
output = new ObjectOutputStream(this.connection.getOutputStream());
input = new ObjectInputStream(this.connection.getInputStream());
do {
try {
message = (String) input.readObject();
System.out.println(messagenum +" Output> " +message);
} catch (EOFException | SocketException e) {
message = null;
}
if (message != null) {
output.writeObject(messagenum +" FromServer> " +message);
output.flush();
++messagenum;
}
} while (message != null);
input.close();
output.close();
this.connection.close();
} catch (IOException | ClassNotFoundException ex) {
System.err.println("Error encountered! Exiting program...");
ex.printStackTrace();
}
}
}
Class 3 - client main
public class EchoClient implements Serializable {
private static final long serialVersionUID = 1L;
private Socket connection;
private ObjectOutputStream output;
private transient ObjectInputStream input;
private String message = "";
private static String serverName;
public static final String DEFAULT_SERVER_NAME = "localhost";
private static int portNum;
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
public EchoClient(String serverName, int portNum) {
this.serverName = serverName;
this.portNum = portNum;
}
public synchronized void runClient() {
try {
connection = new Socket(InetAddress.getByName(serverName), portNum);
output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
do {
System.out.print("Input> ");
message = keyboard.readLine();
if (message != null){
output.writeObject(message);
output.flush();
message = (String) input.readObject();
System.out.println(message);
}
} while (message != null);
input.close();
output.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
switch (args.length) {
case 2:
(new EchoClient(args[0], Integer.parseInt(args[1]))).runClient();
break;
case 1:
(new EchoClient(DEFAULT_SERVER_NAME, Integer.parseInt(args[0]))).runClient();
break;
default:
(new EchoClient(DEFAULT_SERVER_NAME, server.EchoServer.DEFAULT_PORT)).runClient();
}
}
}
Call server.accept() in the loop to accept multiple client connections as mentioned in the other answers. Start a new thread with the Thread.start method instead of Thread.run- What's the difference between Thread start() and Runnable run().
volatile boolean isRunning = true;
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
while(isRunning) {
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).start();
}
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
run server needs to wait for connections in a loop otherwise it will connect once and that is it. It needs to close its connections too. Clean up its threads. that's just in server main. I'm pretty sure this is a duplicate. So keep on researching
As said by efekctive, you need your server.accept() in a loop, else it will accept the first client and exit the program. So put these two lines in runServer() in a loop like this:
boolean isRunning = true;
while(isRunning){
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
}

MulServer - Client communication: After a shutdown, connected clients can still interact[WHY?]

UPDATE: Thank you very Antoniossss and Peter Lawrey!
I created a Multi-Threaded Server - Client Communication.
I have 3 Classes: Server, Client, RequestHandler.
The server opens a ServerSocket and then starts to listen for clients via accept() and if a client connects, he refers the client's task(some String) to the RequestHandler.
The command important to me is "SHUTDOWN".
If the RequestHandler finds this command, he calls a method within the Server to shutdown.
This method is based on the usage Example of the Executor Service:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html (if you do not want to click on the link, see the FAT text for the method)
You do not have to read the code provided below, but in case someone is interested in it I am providing it
The method of the usage Example:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
public class MulServer_v1 {
protected static int portNumber = 8540;
protected static int max_Clients = 3;
protected static boolean shutdownFlag = false;
private static ServerSocket serverSocket;
protected ExecutorService executor;
protected static ArrayList<Socket> socketList = new ArrayList<>();
public MulServer_v1(int portNumber, int poolSize) {
}
public void runServer() {
try {
serverSocket = new ServerSocket(portNumber);
executor = Executors.newFixedThreadPool(max_Clients);
} catch (IOException e) {
System.out.println("Could not create server on specific port");
e.printStackTrace();
}
while (!shutdownFlag) {
try {
Socket clientSocket = serverSocket.accept();
socketList.add(clientSocket);
executor.submit(new RequestHandler_v1(clientSocket));
} catch (IOException e) {
System.out.println("Couldn't accept on the Socket");
executor.shutdown();
e.printStackTrace();
}
}
shutdownAndAwaitTermination();
}
public void shutdownAndAwaitTermination() {
System.out.println("Shutting down..");
executor.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
// Cancel currently executing tasks
System.out.println("komme ich hierhin?");
// Wait a while for tasks to respond to being cancelled
if (!executor.awaitTermination(10, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
executor.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
try {
serverSocket.close();
} catch (IOException e) {
System.out.println("Serversocket konnte nicht geschlossen werden");
e.printStackTrace();
}
System.out.println("I got here!");
for (Socket s : socketList) {
if (s != null) {
try {
s.close();
} catch (IOException e) {
System.out.println("Couldn't close the socket");
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
MulServer_v1 server = new MulServer_v1(portNumber, max_Clients);
server.runServer();
}
}
public class Client_v1 {
public static final String HOSTNAME = "localhost";
public static final int PORTNUMBER = 8540;
private static boolean clientClose = false;
public static void main(String[] args) throws IOException {
System.out.println("Client started");
try (Socket socket = new Socket(HOSTNAME, PORTNUMBER);
PrintWriter out = new PrintWriter(socket.getOutputStream(),
true);
// InputStream test = echoSocket.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in))) {
String userInput;
while ((userInput = stdIn.readLine()) != null && !clientClose) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
// if (userInput.equals("BYE")) {
// break;
// }
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + HOSTNAME);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to "
+ HOSTNAME);
System.exit(1);
}
}
protected static void closeClient() {
clientClose = true;
}
}
public class RequestHandler_v1 implements Runnable {
// private final String password = "passwort";
private final Socket client;
private boolean closeFlag = false;
public RequestHandler_v1(Socket client) {
this.client = client;
}
#Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(client.getOutputStream()));) {
System.out.println("Thread started with name:"
+ Thread.currentThread().getName());
String userInput;
String serverResponse;
while ((userInput = in.readLine()) != null) {
serverResponse = processInput(userInput);
System.out.println("Received message from "
+ Thread.currentThread().getName() + " : " + userInput);
writer.write("Sever Response : " + serverResponse);
writer.newLine();
writer.flush();
if (closeFlag) {
Client_v1.closeClient();
MulServer_v1.socketList.remove(client);
client.close();
}
}
} catch (IOException e) {
System.out.println("I/O exception: " + e);
} catch (Exception ex) {
System.out.println("Exception in Thread Run. Exception : " + ex);
}
}
public String processInput(String input) {
boolean commandFound = false;
String output = "";
try {
if (input.getBytes("UTF-8").length > 255)
output = "Max string length exceeded";
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Pattern allPattern = Pattern
.compile("(?<lower>^LOWERCASE\\s.+)|(?<upper>^UPPERCASE\\s.+)|(?<reverse>^REVERSE\\s.+)|(?<bye>^BYE)|(?<shutdown>^SHUTDOWN passwort)");
Matcher allMatcher = allPattern.matcher(input);
if (allMatcher.find()) {
String lower = allMatcher.group("lower");
String upper = allMatcher.group("upper");
String reverse = allMatcher.group("reverse");
String bye = allMatcher.group("bye");
String shutdown = allMatcher.group("shutdown");
commandFound = true;
if (lower != null) {
output = lower.substring(10).toLowerCase();
}
if (upper != null) {
output = upper.substring(10).toUpperCase();
}
if (reverse != null) {
output = new StringBuilder(reverse.substring(8)).reverse()
.toString();
}
if (bye != null) {
output = "BYE";
closeFlag = true;
}
if (shutdown != null) {
output = "SHUTDOWN";
MulServer_v1.shutdownFlag = true;
closeFlag = true;
}
} else {
commandFound = false;
output = "UNKNOWN COMMAND";
}
if (commandFound) {
output = "OK ".concat(output);
} else {
output = "ERROR ".concat(output);
}
return output;
}
}
Now the shutting down works, but new clients can connect after the shutdown. How is that possible?
This is Sysout I used to check:
Shutting down..
Thread started with name:pool-1-thread-3
Received message from pool-1-thread-3 : . //<--This (Sending a message) should //NOT be able to happen, since executor.shutdown(); has already been called.
The thing is that your signaling is broken:
while (!shutdownFlag) {
try {
Socket clientSocket = serverSocket.accept();
executor.execute(new RequestHandler_v1(clientSocket));
} catch (IOException e) {
accept() is blocking operation - it blocks until new connection comes right? And here is the culrpit. After you send your "shutdown" command, current thread will unblock, submit the tast, pass the while condition and block again on accept(). After this, proper executor will set the flag to false, but server is still accepting so pool is never shut down.
Another attempt to connect should wake the server and honor shutdownFlag breaking out of the loop and causing all handlers to die after 10 seconds.
Also:
while ((userInput = in.readLine()) != null) {
is a blocking operation - it block your tasks from finishing thus pool will newer shut down. null will be returned if stream will end - either naturally or by an exception. You are not ending the stream on neither of sides. So it will block.
ExecutorsService#shutdownNow() does not mean that threads from pool will be killed - they are signalled to terminate, and threads are to gracefully terminate just like #PeterLawrey mentioned, using Thread.isTerminated() flag.
Proof of concept that closing the socket will break from blocked IO operation:
public class Buffers {
private static Socket client;
static class ServerThread extends Thread {
#Override
public void run() {
try {
ServerSocket serverS = new ServerSocket(1099);
client = serverS.accept();
client.getOutputStream().write('a');
client.getOutputStream().flush();
Thread.sleep(2000);
client.close();
} catch (IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class ClientThread extends Thread {
#Override
public void run() {
try {
Thread.sleep(500);
Socket socket = new Socket("127.0.0.1", 1099);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Will try to read");
String line=null;
while ((line = input.readLine()) != null) { // block here
System.out.println("Read " + line); // will never come here
}
} catch (Exception e) {
System.out.println("Server closed the connection!");
}
super.run();
}
}
public static void main(String[] args) throws InterruptedException {
new ServerThread().start();
ClientThread t = new ClientThread();
t.start();
t.join();
}
If you comment client.close(); app will never end just like in your case.

Separating Client class from JFrame [duplicate]

A few days ago i tried to create a server - client or client Server as an experiment to learn about socket using a thread but then someone told me that i should use swingWorker. I did some research how to use and have implemented it in as practice but it still doesn't work. the swingWorker thread doesn't look like it is running even tho i get a connection and have used .excute(). If you guys can help spot where i am doing wrong that will be great. SwingWorker class is in the startSever() and startClient() method.
private void startServer() {
SwingWorker <Void, String> runningServer = new SwingWorker<Void, String>(){
protected Void doInBackground() {
try {
listeningSocket = new ServerSocket(port);
System.out.println("waiting for connection");
connection = listeningSocket.accept();
connected = true;
System.out.println("Connected");
String incomeMessage =null;
while(connected){
inStream = connection.getInputStream();
inDataStream = new DataInputStream(inStream);
if (myMessage !=null){
outStream = connection.getOutputStream();
outDataStream = new DataOutputStream(outStream);
outDataStream.writeUTF(myMessage);
}
if((incomeMessage = inDataStream.readUTF())!=null){
clientMessage = incomeMessage;
publish(clientMessage);
incomeMessage =null;
}
}
} catch (IOException e) {
clientMessage = "Connection Lost";
}
return null;
}
runningServer.execute();
}
Here's a VERY basic example.
Basically, because you program requires asynchronous communications (that is, you need to be able to read from the socket AND write to it at the same time), you need to offload each stream to a separate thread.
The management process of this example is, well, no existent. Realistically, you should have some kind of "connection" manager that would be able to cleanly close the output and input threads so that, for example, when the user types "bye", the output thread would be able to tell the connection manager that the connection should be terminated. It would then tell the input thread to stop reading any new message and terminate...
Client
public class Client {
public static void main(String[] args) {
try {
Socket master = new Socket("localhost", 8900);
new Thread(new InputHandler(master)).start();
new Thread(new OuputHandler(master)).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static class InputHandler implements Runnable {
private Socket socket;
public InputHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean commune = true;
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (commune) {
String text = reader.readLine();
System.out.println("\n<server> " + text);
if (text.toLowerCase().equals("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
public static class OuputHandler implements Runnable {
private Socket socket;
public OuputHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean commune = true;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Scanner scanner = new Scanner(System.in);
while (commune) {
System.out.print("> ");
String text = scanner.nextLine();
writer.write(text);
writer.newLine();
writer.flush();
if (text.equalsIgnoreCase("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
writer.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
}
Server
public class Server {
public static void main(String[] args) {
try {
ServerSocket master = new ServerSocket(8900);
Socket socket = master.accept();
new Thread(new InputHandler(socket)).start();
new Thread(new OuputHandler(socket)).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static class InputHandler implements Runnable {
private Socket socket;
public InputHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean commune = true;
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (commune) {
String text = reader.readLine();
System.out.println("\n<client> " + text);
if (text.toLowerCase().equals("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
public static class OuputHandler implements Runnable {
private Socket socket;
public OuputHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean commune = true;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Scanner scanner = new Scanner(System.in);
while (commune) {
System.out.print("> ");
String text = scanner.next();
writer.write(text);
writer.newLine();
writer.flush();
if (text.equalsIgnoreCase("bye")) {
commune = false;
}
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
writer.close();
} catch (Exception e) {
}
try {
socket.close();
} catch (Exception e) {
}
}
}
}
}
Update (whine)
While I have your source code in front of me...
There should very, very, rarely be a need to do textMessage.addKeyListener(this)
Because you are using a JTextField, you should be using a ActionListener instead. There are a a number of important reasons for this, but for you, the main one would be the fact that a "accept" action is Look and Feel dependent. While most systems do use Enter as there "accept" action, is not a guarantee.
Have a look at How to Write a Action Listener for more information
Given the general complexity of what you are trying to do, +1 for a overall good attempt!
Using this example, the following changes work with a single telnet client.
private PrintWriter out;
...
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
myMessage = friendLabel + textMessage.getText();
if (out != null) {
out.println(myMessage);
}
...
}
...
protected Void doInBackground() {
try {
listeningSocket = new ServerSocket(port);
System.out.println("Waiting for connection");
connection = listeningSocket.accept();
connected = true;
System.out.println("Connected");
Scanner in = new Scanner(connection.getInputStream());
out = new PrintWriter(connection.getOutputStream(), true);
publish("Connected");
while (true) {
publish(in.nextLine());
}
} catch (IOException e) {
clientMessage = "Connection Lost";
try {
connection.close();
System.out.println("Closed");
} catch (IOException e1) {
e1.printStackTrace();
connected = false;
}
}
return null;
}
I see your server port is 8900 and your client port is 8900 too. I am not sure if it matters if the server and client are running on the same machine...

Java threads not starting / working as expected

I am implementing a simple client-server architecture where multiple clients should be able to connect to the server and strings could be exchanged between the server and client.
My idea is that I'll have two threads on each side: a listener, constantly checking if there is anything new in the inputstream, and a writer thread, that writes into the socket if there is something to write.
However, the second thread doesn't even start... Only the first sysout is displayed.
//start new thread to handle client input
new Thread(
new ServerWorker(clientSocket, this, this.getIdCounter())).start();
System.out.println("server side listener started");
//start new thread to handle client output
new Thread(new ServerWorkerListener(clientSocket)).start();
System.out.println("server side writer started");
Here is some code from the ServerWorker:
public void run() {
try {
OutputStream output = clientSocket.getOutputStream();
while (true) {
// output.write(("Pling!\n\n").getBytes());
for (Client tempClient : server.getClientList()) {
if ((tempClient.getId() == this.id)
&& tempClient.isShouldSend()) {
output.write((tempClient.getOutputStream() + "\n\n")
.getBytes());
tempClient.setInputStream("");
tempClient.setShouldSend(false);
}
}
}
} catch (IOException e) {
System.out.println("Error in serverWorker");
e.printStackTrace();
}
}
I really don't know what I'm missing...
Whole of ServerWorker:
public class ServerWorker implements Runnable {
protected Socket clientSocket = null;
protected String serverText = null;
protected int id;
protected Server server;
public ServerWorker(Socket clientSocket, Server server,
int id) {
this.clientSocket = clientSocket;
this.serverText = serverText;
this.id = id;
this.server = server;
}
public void run() {
try {
OutputStream output = clientSocket.getOutputStream();
while (true) {
// output.write(("Pling!\n\n").getBytes());
for (Client tempClient : server.getClientList()) {
if ((tempClient.getId() == this.id)
&& tempClient.isShouldSend()) {
output.write((tempClient.getOutputStream() + "\n\n")
.getBytes());
tempClient.setInputStream("");
tempClient.setShouldSend(false);
}
}
}
} catch (IOException e) {
System.out.println("Error in serverWorker");
e.printStackTrace();
}
}
}
Whole of ServerWorkerListener:
public class ServerWorkerListener implements Runnable {
private BufferedReader input;
private Socket clientSocket;
public ServerWorkerListener(Socket clientSocket) {
this.clientSocket = clientSocket;
run();
}
#Override
public void run() {
System.out.println("its running");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
while (true) {
System.out.println("it's looping");
String inputLine = null;
if ((inputLine = in.readLine()) != null) {
JOptionPane.showMessageDialog(null, inputLine, "InfoBox: "
+ "Message from client",
JOptionPane.INFORMATION_MESSAGE);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about client");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to client");
System.exit(1);
}
}
}
You are invoking run() inside the constructor of ServerWorkerListener, which you must not do. The new thread ought to invoke run(), otherwise, since it contains an infinite loop, it will never return from the constructor and hence never invoke the Thread’s constructor, not to speak of its start method. So removing run() the invocation from the constructor should solve the problem.

Why is it my code cannot run many clients in java multithreading?

Why is this code nott accumulating many clients?
I'm new to java.
It only runs for only 1 client.
Can anyone explain why it doesn't support multiple clients for socket programming?
import java.net.*;
import java.io.*;
/**
* Demo Server: Contains a multi-threaded socket server sample code.
*/
public class ServerDemo extends Thread
{
final static int _portNumber = 5559; //Arbitrary port number
public static void main(String[] args)
{
try {
new ServerDemo().startServer();
} catch (Exception e) {
System.out.println("I/O failure: " + e.getMessage());
e.printStackTrace();
}
}
public void startServer() throws Exception {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(_portNumber);
} catch (IOException e) {
System.err.println("Could not listen on port: " + _portNumber);
System.exit(-1);
}
while (listening) {
handleClientRequest(serverSocket);
}
serverSocket.close();
}
private void handleClientRequest(ServerSocket serverSocket) {
try {
new ConnectionRequestHandler(serverSocket.accept()).run();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Handles client connection requests.
*/
public class ConnectionRequestHandler implements Runnable{
private Socket _socket = null;
private PrintWriter _out = null;
private BufferedReader _in = null;
public ConnectionRequestHandler(Socket socket) {
_socket = socket;
}
public void run() {
System.out.println("Client connected to socket: " + _socket.toString());
try {
_out = new PrintWriter(_socket.getOutputStream(), true);
_in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
String inputLine, outputLine;
BusinessLogic businessLogic = new BusinessLogic();
outputLine = businessLogic.processInput(null);
_out.println(outputLine);
//Read from socket and write back the response to client.
while ((inputLine = _in.readLine()) != null) {
outputLine = businessLogic.processInput(inputLine);
if(outputLine != null) {
_out.println(outputLine);
if (outputLine.equals("exit")) {
System.out.println("Server is closing socket for client:" + _socket.getLocalSocketAddress());
break;
}
} else {
System.out.println("OutputLine is null!!!");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally { //In case anything goes wrong we need to close our I/O streams and sockets.
try {
_out.close();
_in.close();
_socket.close();
} catch(Exception e) {
System.out.println("Couldn't close I/O streams");
}
}
}
}
/**
* Handles business logic of application.
*/
public static class BusinessLogic {
private static final int LoginUserName = 0;
private static final int LoginPassword = 1;
private static final int AuthenticateUser = 2;
private static final int AuthSuccess = 3;
private int state = LoginUserName;
private String userName = null;
private String userPassword = null;
public String processInput(String clientRequest) {
String reply = null;
try {
if(clientRequest != null && clientRequest.equalsIgnoreCase("login")) {
state = LoginPassword;
}if(clientRequest != null && clientRequest.equalsIgnoreCase("exit")) {
return "exit";
}
if(state == LoginUserName) {
reply = "Please Enter your user name: ";
state = LoginPassword;
} else if(state == LoginPassword) {
userName = clientRequest;
reply = "Please Enter your password: ";
state = AuthenticateUser;
} else if(state == AuthenticateUser) {
userPassword = clientRequest;
if(userName.equalsIgnoreCase("John") && userPassword.equals("doe")) {
reply = "Login Successful...";
state = AuthSuccess;
} else {
reply = "Invalid Credentials!!! Please try again. Enter you user name: ";
state = LoginPassword;
}
} else {
reply = "Invalid Request!!!";
}
} catch(Exception e) {
System.out.println("input process falied: " + e.getMessage());
return "exit";
}
return reply;
}
}
}
You are not starting the thread in your code.
instead of
new ConnectionRequestHandler(serverSocket.accept()).run();
call
new Thread(new ConnectionRequestHandler(serverSocket.accept())).start();
method run() of your Runnable class will be invoked when you start your thread, you should not call this run() method directly.
Instead of that you should make a thread instance via
Thread myThread = new Thread(aRunnableInstance);
and start it:
myThread.start();
You're not starting a new thread, but simply running the RequestHandler code in the main thread.
Look up the difference between Thread.start() and Runnable.run(). This question might help.
Edit:
You're just missing the part where you would tell the JVM to create a new Thread to execute your Runnable code. Without a call to Thread.start() your current (and only) thread would be busy handling one request at a time. You want one Thread per request, basically. There are more advanced ways of doing this (thread pools and whatnot), but this should get you started.
private void handleClientRequest(ServerSocket serverSocket) {
try {
new Thread(ConnectionRequestHandler(serverSocket.accept())).start();
} catch (IOException e) {
e.printStackTrace();
}
}

Categories