Client code:
import java.io.BufferedReader;
import java.io.IOError;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.Scanner;
import javax.swing.*;
import java.io.*;
public class messages_client
{
static BufferedReader in;
static Scanner sc;
static PrintWriter out;
public static void main(String args[])
{
try{
JFrame frame=new JFrame();
Socket client=new Socket("localhost",59001);
in=new BufferedReader(new InputStreamReader(client.getInputStream()));
out=new PrintWriter(client.getOutputStream(),true);
sc=new Scanner(System.in);
boolean running=false;
String input=in.readLine();
System.out.println(input);
String name=sc.next();
out.println(name);
running=true;
Thread send=new Thread(new send());
Thread recieve=new Thread(new recieve());
if(running == true)
{
while(true)
{
send.start();
recieve.start();
}
}
} catch(IOException e){}
}
public static class send implements Runnable
{
#Override
public void run()
{
String message=sc.nextLine();
out.println(message);
}
}
public static class recieve implements Runnable
{
#Override
public void run()
{
try {
String input=in.readLine();
System.out.println(input);
} catch (IOException e) {
}
}
}
}
Server code:
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.Executors;
public class messages_server
{
private static ServerSocket server;
private static Set<PrintWriter> printwriters=new HashSet<>();
public static void main(String args[])
{
try{
server=new ServerSocket(59001);
var pool=Executors.newFixedThreadPool(5);
System.out.println("Server is running");
while(true)
{
pool.execute(new ClientHandler(server.accept()));
}
} catch(IOException e)
{
} finally
{
try{
server.close();
} catch(IOException e){}
}
}
private static class ClientHandler implements Runnable
{
private Socket client;
private static PrintWriter out;
private static BufferedReader in;
private static String message;
private static String name;
ClientHandler(Socket client)
{
this.client=client;
}
#Override
public void run()
{
try{
out=new PrintWriter(client.getOutputStream(),true);
in=new BufferedReader(new InputStreamReader(client.getInputStream()));
send("Name: ");
name=in.readLine();
System.out.println(name);
out.println("1");
broadcast(name+" has joined the chat");
while(true)
{
message=in.readLine();
broadcast(name+":"+message);
}
} catch(IOException e){}finally
{
if(in != null)
{
printwriters.remove(out);
broadcast(name+" has left the chat");
}
try{
client.close();
}catch(IOException e){}
}
}
public void broadcast(String message)
{
for(PrintWriter printwriter:printwriters)
{
printwriter.println(message);
}
}
public void send(String message)
{
out.println(message);
}
}
}
I have created this simple Chat Application where multiple users can join a common chat.The Server creates a different thread for each client and continuously recieves and broadcasts data.The client to has two threads: "send" "recieve" which send and recieve data continuosly.
The Server works fine but when I run the client after typing in my name there shows IllegalThreadStateException.
Please help and suggest if there is anyway I can improve this code too.
I think you're confused about what Thread's start() method does.
In your code:
Thread send = new Thread(new send());
Thread recieve = new Thread(new recieve());
You create exactly one thread (send) for sending, and exactly one (recieve - note you have a typo, it's "receive". English is weird) for receiving.
You then:
while(true)
{
send.start();
recieve.start();
}
repeatedly (while loop) invoke .start() on these single threads.
That's not how it works: You can only start a Thread object once, ever. If you invoke .start() the second time, you get IllegalThreadStateException, because the state is 'STARTED' and you can't call .start() on such a thread.
What's not quite clear is your intent. Were you intending to continually start threads? Then you'd have to create a new thread object every time and then start it, i.e. move the Thread send = ...; code inside the while loop. However, I can't imagine you want that: If you stick that in a while(true) the system will create an infinite amount of threads, starts them, and, naturally, crashes very very quickly and very definitely if you try that.
If your intent is simply to keep that one send and one receive thread from continuing to run - there is no need to repeatedly invoke .start() or do anything else from the main method - your receive and send runnables already have loops (they both have a while(true) loop of their own).
If you intent is to restart any thread that somehow stopped itself, 'just in case' - that's not how it works. Once a thread ends you can't start it again - you'd have to make a new one. And as discussed before, just making an endless amount of threads is just going to lead to a swift crash. You CAN ask a thread if it is no longer running, and then create a new thread and start the new one, but you shouldn't defensively program.
Let me clarify that, because the term 'defensive programming' is overloaded: You should not write code to deal with situations that are not understood. In this case, the situation is: "I dont quite know how, but lets just imagine the send thread is somehow stopped. I want to restart it if this happens". The reason that kind of defensive programming is bad, is: By definition you don't really know what happened (after all, you have no idea how some state COULD happen, therefore it is likely that you're missing rather crucial understanding about what's going on when the to you impossible situation does evidently occur), so the odds that you're doing the right thing (that 'just restart it' is the right answer to 'huh, weird, that thread stopped and I do not understand why') are low.
Most likely, the situation you can't fathom happening can, in fact, never happen, so you wrote a bunch of code that never ever runs. This leads to the biggest problem of defensive programming: The code is untestable, and rarely (often never) runs, which means any bugs in it go completely unnoticed. So you now have useless code that if it ever becomes useful, doesn't work at all.
It is FAR better to just hard-crash out with an exception in such impossible cases. At least then, if it does occur, you have a lead on investigating. Only after you understand can you write code that deals with the situation.
Related
I have received some code through a school project and I'm failing to understand the purpose of the use of threading in this scenario. The project requires use of a multi threading server to pass. I have the following thread implementation which of a new instance is created every time a new client connects.
The problem is that they are not using the run-method, in my understanding the thread exists when it finishes running the run-method. But even after the thread should have finished running it manages to send further the messages from the propertyStateListener. Why does this work and does this really count as a multi-threaded server?
Starts an instance of the ClientHandler every time a new client connects:
#Override
public void run() {
while (true) {
MessageProducer mp;
try {
Socket socket = serverSocket.accept();
new ClientHandler(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The actual ClientHandler:
private class ClientHandler extends Thread implements PropertyChangeListener {
private Socket socket;
private ObjectInputStream ois;
private ObjectOutputStream oos;
private Message messagerecieved;
public ClientHandler(Socket socket) throws IOException {
this.socket = socket;
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
messageManager.registerListener(this);
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
messagerecieved = (Message) evt.getNewValue();
try {
oos.writeObject(messagerecieved);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
}
}
The problem is that they are not using the run-method, in my understanding the thread [exits] when it finishes running the run-method. But even after the thread should have finished running it manages to send further the messages from the propertyStateListener.
You are correct that the code is confusing for sure. They are creating a thread with each instance of ClientHandler but there is no run() method so the thread immediately exits after start() is called. The code would actually still work if ClientHandler did not extend thread.
Why does this work
It is the messageManager thread which is calling back to the ClientHandler.propertyChange(...) method which writes the results back to the socket, not the ClientHandler thread.
does this really count as a multi-threaded server?
There certainly are 2 threads at work here because you have the socket-accept thread and the messageManager thread. Whether or not this is a "multi-threaded server" depends on the assignment I guess. Certainly if there was supposed to be a thread per client then this code does not do that.
I am getting a NullPointerException when I run my code. I have narrowed down the problem to line 38: when it is commented out the program doesn't give any errors. I just have "test" here for now.
out.println("test")
The run method is immediately started with the following two lines in another class
Client test = new Client();
test.start();
And when a button is pressed the following code is executed which runs the sendToServer method
Client test = new Client();
test.sendToServer(cipherText)
Below is the full code for my Client class.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client extends Thread{
String line = "";
String cipherText = "";
BufferedReader in;
PrintWriter out;
public void run(){
String serverAddress = "00.000.000.000";
try{
Socket socket = new Socket(serverAddress, 8888);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
}
catch(IOException e){
e.printStackTrace();
}
while (true) {
try{
line = in.readLine();
}
catch(IOException e){
e.printStackTrace();
}
System.out.println(line);
}
}
public void sendToServer(String in) {
out.println("test");
}
}
Thanks for looking, I am still learning java so excuse any obvious mistakes.
You have in the beggining of the class:
PrintWriter out;
if you don't call run() [is where you initialize it] before sendToServer(), "out" would never be initialized and will be null.
That is because you have used PrintWriter out; as your class member but you have not initialized it. By default, all un-initialized member objects are initialized with null. If sendToServer() is called first, out will be null and you will get NullPointerException.
EDIT
Problem is that you are trying to invoke run() and sendToServer() methods on two separate instances of Client.
Client test = new Client(); // First instance
test.start(); // which calls run() and then initializes out variable.
Then a second instance is created from:
Client test = new Client(); // Second instance
test.sendToServer(cipherText); // since out is not initialized for this instance, you are getting NPE
I suppose you are using Client object in a multi-threaded environment, in that case I would suggest you to make sure that both threads are using same instance of Client object. Also if Client instance is being shared, you might want to make access to out variable synchronized and also make sure that Client's run method is executed first before button is pressed (which in turn calls sendToServer()).
Your function assumes out Printwriter will be initialized, but if there is an exception in the socket initialization, it will never by initialized. Two things I would do...
1. Initialize out to null at the top of the run method.
2. protect your sendToServer code...
public void sendToServer(String in) throws NullPointerException
{
if (out == null)
{
throw new NullPointerException("Out is null.");
}
out.println("test");
}
I have gone through so many tutorials on Synchronization now that my head is spinning. I have never truly understood it :(.
I have a Java server(MainServer), that when a client connects creates a new thread(ServerThread) with a DataOutputStream.
The client talks to the ServerThread and the ServerThread responds. Every now and then the MainServer will distribute a message to all clients utilizing each ServerThread's DataOutputStream object.
I am quite certain that every now and then my issue is because both the MainServer and ServerThread are trying to send something to the client at the same time. Therefore I need to lock on the DataOutputStream object. For the life of me I cannot understand this concept any further. Every example I read is confusing.
What is the correct way to handle this?
ServerThread's send to client method:
public void replyToOne(String reply){
try {
commandOut.writeUTF(reply);
commandOut.flush();
} catch (IOException e) {
logger.fatal("replyToOne", e);
}
logger.info(reply);
}
MainServer's distribute to all clients method:
public static void distribute(String broadcastMessage){
for (Map.Entry<String, Object[]> entry : AccountInfoList.entrySet()) {
Object[] tmpObjArray = entry.getValue();
DataOutputStream temporaryCOut = (DataOutputStream) tmpObjArray[INT_COMMAND_OUT]; //can be grabbed while thread is using it
try {
temporaryCOut.writeUTF(broadcastMessage);
temporaryCOut.flush();
} catch (IOException e) {
logger.error("distribute: writeUTF", e);
}
logger.info(broadcastMessage);
}
}
I am thinking I should have something like this in my ServerThread class.
public synchronized DataOutputStream getCommandOut(){
return commandOut;
}
Is it really that simple? I know this has likely been asked and answered, but I don't seem to be getting it still, without individual help.
If this were me.....
I would have a LinkedBlockingQueue on each client-side thread. Then, each time the client thread has a moment of idleness on the socket, it checks the queue. If there's a message to send from the queue, it sends it.
Then, the server, if it needs to, can just add items to that queue, and, when the connection has some space, it will be sent.
Add the queue, have a method on the ServerThread something like:
addBroadcastMessage(MyData data) {
broadcastQueue.add(data);
}
and then, on the socket side, have a loop that has a timeout-block on it, so that it breaks out of the socket if it is idle, and then just:
while (!broadcastQueue.isEmpty()) {
MyData data = broadcastQueue.poll();
.... send the data....
}
and you're done.
The LinkedBlockingQueue will manage the locking and synchronization for you.
You are on the right track.
Every statement modifying the DataOutputStream should be synchronized on this DataOutputStream so that it is not concurrently accessed (and thus do not have any concurrent modification):
public void replyToOne(String reply){
try {
synchronized(commandOut) { // writing block
commandOut.writeUTF(reply);
commandOut.flush();
}
} catch (IOException e) {
logger.fatal("replyToOne", e);
}
logger.info(reply);
}
And:
public static void distribute(String broadcastMessage){
for (Map.Entry<String, Object[]> entry : AccountInfoList.entrySet()) {
Object[] tmpObjArray = entry.getValue();
DataOutputStream temporaryCOut = (DataOutputStream) tmpObjArray[INT_COMMAND_OUT]; //can be grabbed while thread is using it
try {
synchronized(temporaryCOut) { // writing block
temporaryCOut.writeUTF(broadcastMessage);
temporaryCOut.flush();
}
} catch (IOException e) {
logger.error("distribute: writeUTF", e);
}
logger.info(broadcastMessage);
}
}
Just putting my 2 cents:
The way I implement servers is this:
Each server is a thread with one task only: listening for connections. Once it recognizes a connection it generates a new thread to handle the connection's input/output (I call this sub-class ClientHandler).
The server also keeps a list of all connected clients.
ClientHandlers are responsible for user-server interactions. From here, things are pretty simple:
Disclaimer: there are no try-catches blocks here! add them yourself. Of course you can use thread executers to limit the number of concurrent connections.
Server's run() method:
#Override
public void run(){
isRunning = true;
while(isRunning){
ClientHandler ch = new ClientHandler(serversocket.accept());
clients.add(ch);
ch.start();
}
}
ClientHandler's ctor:
public ClientHandler(Socket client){
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
}
ClientHandler's run() method:
#Override
public void run(){
isConnected = true;
while(isConnected){
handle(in.readObject());
}
}
and handle() method:
private void handle(Object o){
//Your implementation
}
If you want a unified channel say for output then you'll have to synchronize it as instructed to avoid unexpected results.
There are 2 simple ways to do this:
Wrap every call to output in synchronized(this) block
Use a getter for output (like you did) with synchronized keyword.
I've just got my feet wet with multi-threading and its really awesome. I find myself trying to figure out new ways I can use it make things better and I think I found one but I'm unsure how to design the program for this.
Here's the situation. I have a queue server that multiple clients consume and produce data to but to kick start the process I run a java program on to put some initial data for them to start. then my program is done and I have excess capacity on the queue server but nothing is really running on it. So I want to try to do some maintenance tasks, run a service, and do low priority stuff.I'm not sure how do that though. How do I design a program that does completely different tasks concurrently?
Typically I just wrap my programs in a while (true) loop and it does a single task and I realize I cannot do two while loops at the same time in the same process(maybe nested?). To show a simplified example, I put a bunch of code that runs a runnable(maybe it'll process a low priority queue) and a service that monitors a socket and replies back(I might want to add more depending on cpu usage). How do I get them all to work together? Is there a better way to design it(I know long term its probably better to run multiple java processes but right now I am just trying to manage a single file and I suspect there's a way to give the socket service a higher priority than processing the queue within the file but if they are both running in different files I don't know how to lower one over the other instead of them fighting for resources)?
Thanks and I'll edit this question if it turns out I'm explaining this totally wrong. But in a nutshell, I want it to provide a service to other systems(server socket, in the example) and when its idle I want it to do a few other tasks.
Example(if you understand what I'm asking this code may not be necessary to read):
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class multipleThreads {
private ServerSocket server;
private int port = 7777;
public void ServerSocketExample() {
try {
server = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("starting");
ServerSocketExample example = new ServerSocketExample();
example.handleConnection();
while (true) {
//monitor low low priority queue
}
}
public void handleConnection() {
System.out.println("Waiting for client message...");
//
// The server do a loop here to accept all connection initiated by the
// client application.
//
while (true) {
try {
Socket socket = server.accept();
new ConnectionHandler(socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ConnectionHandler implements Runnable {
private Socket socket;
public ConnectionHandler(Socket socket) {
this.socket = socket;
Thread t = new Thread(this);
t.start();
}
public void run() {
try
{
//
// Read a message sent by client application
//
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String message = (String) ois.readObject();
System.out.println("Message Received: " + message);
//
// Send a response information to the client application
//
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi...");
ois.close();
oos.close();
socket.close();
System.out.println("Waiting for client message...");
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class MonitorQueue implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
//do work when stuff comes in the queue
}
}
I strongly recommend you take a look at this project: Java Concurrent Animated. I found this probably the best way to get my head around concurrency concepts in Java: it's animated, interactive, and you can just take one concept at a time and get a good understanding.
http://sourceforge.net/projects/javaconcurrenta/
Take a look at the java.util.concurrent package. It's full off goodies for doing exactly the kinds of things you describe.
In particular, check out the Executors factory class which lets you build Thread Pools that allow multiple tasks to be scheduled and run concurrently on any number of Threads you specify.
Oracle has some great tutorials on using Executors:
http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
http://docs.oracle.com/javase/tutorial/essential/concurrency/exinter.html
Concurrency is hard, you can read Java Concurrency in Practice, but even the experts have difficulties.
Look for a training course in your area.
I would like to recommend Concurrency Specialist Courses which is based on Java Concurrency in Practice and endorsed by the author, Brian Goetz
Context: I am reading data from a serial port at 115.2 Kbaud. The read data is printed using a PrintWriter that I then have appending to a JTextArea.
Everything works well, but the text in the JTextArea does not appear until the method sending the stream from the serial port to my PrintWriter finishes. I'd like it to display closer to real-time, as I will at times be receiving upwards of 20-30 MB of text at a time, and how the general flow of text changes as the program executes would be valuable.
I am using the PrintWriter to JTextArea method here. I think the solution probably has to do with Threads and PipedWriter/PipedReader, but every attempt I've made to implement that has failed miserably.
Thank you for your help.
//code calling method; VerifierReader does not inherit from Reader
//or any such class. it's wholly homegrown. I send it the PrintWriter
//as out, telling it to output there
verifierInstance=new VerifierReader("COM3", verifierOutputLocString.getText());
verifierInstance.setSysOutWriter(out);
verifierInstance.readVerifierStream();
// and the relevant code from VerifierReader
public void setSysOutWriter (PrintWriter outWriter) {
sysOutWriter=new PrintWriter(outWriter);
}
public void readVerifierStream() throws SerialPortException,
InterruptedException{
try{
sysOutWriter.println("Listening for verifier...");
//sysOutWriter.flush();
verifierPort.addEventListener(new verifierListener());
lastReadTimer=System.currentTimeMillis();
while(verifierPort.isOpened()) {
Thread.sleep(1000);
//System.out.println(timeOut);
if( ((long)(System.currentTimeMillis()-lastReadTimer))>timeOut){
sysOutWriter.println("Finished");
verifierPort.removeEventListener();
verifierPort.closePort();
}
}
}
finally {
if (verifierPort.isOpened()) {
verifierPort.closePort();
}
bfrFile.close();
}
}
private class verifierListener implements SerialPortEventListener{
String outBuffer;
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){//If data is available
timeOut=200;
lastReadTimer=System.currentTimeMillis();
if(event.getEventValue() > 0){//Check bytes count in the input buffer
try {
byte[] buffer = verifierPort.readBytes(event.getEventValue());
outBuffer=new String(buffer);
bfrFile.print(outBuffer);
sysOutWriter.print(outBuffer);
//bfrFile.flush();
//sysOutWriter.flush();
}
catch (SerialPortException ex) {
sysOutWriter.println(ex);
}
}
}
}
}
Edit:
I've attempted what was recommended below, and have made the following changes:
private class VerifierTask extends SwingWorker<Void, String> {
public VerifierTask() throws IOException, SerialPortException, InterruptedException{
verifierInstance= new VerifierReader(streamReader);
verifierInstance.setReaderIO("COM3", verifierOutputLocString.getText());
verifierInstance.readVerifierStream();
}
#Override
protected Void doInBackground() throws IOException{
int charItem;
char[] charBuff = new char[10];
String passString;
while ((charItem = streamReader.read(charBuff, 0, 10)) !=-1) {
passString = new String(charBuff);
publish(passString);
}
return null;
}
#Override
protected void process(List<String> outList) {
for (String output : outList) {
outputArea.append(output);
}
}
}
was added, and I changed my button to immediately invoke a new instance of the VerifierTask class, in addition to making VerifierReader implement a PipedWriter for output (with all of that being Strings).
I'm not sure what I'm doing wrong here. When this code is executed the Java process just freezes indefinitely.
Am I assuming correctly that a VerifierReader created in any VerifierTask thread is tied to that thread, and thus my thread.sleep and while(true) statements no longer pose a problem?
Don't call Thread.sleep or do while (true) on the main Swing event thread, the EDT. Ever. Instead do this sort of thing in a background thread such as one provided via a SwingWorker. You would use the publish/process method pair to get intermediate results to your JTextArea.
For more on this, please check out the tutorial: Concurrency in Swing.