Using a Synchronized collection between threads - java

Code -> http://pastebin.com/1PFCGWQy
Blocks that I'm having problems with
class ClientSender implements Runnable {
Socket server;
ServerClientFrontEnd SCFE;
public ClientSender(Socket server, ServerClientFrontEnd SCFE){
this.server = server;
this.SCFE = SCFE;
}
public void run(){
try(ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream())){
//System.out.println("Client chat ver. 0.1");
//Scanner get = new Scanner(System.in);
while(!server.isClosed()){
//System.out.print("YOU:");
if(!SCFE.synchronizedOutputCollection.isEmpty()) // Here
{
logger.info("Has made it to ClientSender!");
String string = SCFE.synchronizedOutputCollection.firstElement();
logger.info(string);
out.writeObject(string); // Here
logger.info("Output Queue: " + SCFE.synchronizedOutputCollection.toString());
}
//else{ logger.info("It failed the conditional"); }
}
} catch (IOException ex) {
//logger.info("Closing connection...");
//System.exit(0);
}
}
}
class ClientReceiver implements Runnable {
Socket server;
ServerClientFrontEnd SCFE;
public ClientReceiver(Socket server, ServerClientFrontEnd SCFE){
this.server = server;
this.SCFE = SCFE;
}
public void run(){
try(ObjectInputStream in = new ObjectInputStream(server.getInputStream())){
while(!server.isClosed()){
SCFE.ChatBox.setText(SCFE.ChatBox.getText() + "\nOTHER: " + (String) in.readObject()); //Here
logger.info("Receiver has read object!");
}
} catch (IOException ex) {
logger.info("Closing connection");
System.exit(0);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
For some reason, I can not get this to work. I already got it working on a command-line environment, quite perfectly, but I wanted to port it to a graphical user interface and this problem has had me stumped for more than on hour. I didn't know how to handle the fact that Client's original class called other threads which I needed to send and receive the information to and from the server.
Basically, my program works by having the client connect to the server via a ServerSocket, which THEN processes each request. Of course, I've just recently learned about sockets on Thursday but I wanted to make a program of my own... anyway, moving on, the problem is with the ServerClientFrontEnd Class, which for some reason, and I don't know how for the life of me, the collection I'm using to get the inputted text either remains empty or it just will not read from it.
Maybe it might have to do with my while loop, but it worked perfectly before. I have a TON of loggers everywhere to log everything, and if I add an else statement when it checks if the collection is empty, it definitely activates the else statement repeatedly, EVEN AFTER the synchronizedOutputCollection was given a value. In fact, I even print the value inside of the collection when the send button is pressed. In fact, when I attempt a similar print statement inside the thread, the collection is empty and it remains empty.
How can I share a synchronized collection of objects among threads? This question is plaguing me and I would really appreciate a reply.
Also this is runnable, you just have to activate server and 2 clients to test it. P.S I have tried BlockingQueues but they make the GUI thread to freeze up because the queue is never read from, causing a deadlock.

As #markspace pointed out in a comment you have lots of funny things going on in your code. You should take a step backward, go back to the command line interface and rework your entire class structure. Remove those inner classes, use some interfaces like MessageListener or ConnectionListnener that your client or server uses to talk to other classes (like your GUI) about things like messages received or connection created/lost.
When you get done your client main method should look very simple:
public static void main(String [] args) {
Client client = new Client("127.0.0.1");
client.addMessageListener(new MessageListener() {
public void messageRecieved(String message) {
System.out.println(message);
}
});
client.connect();
System.out.println("Connected to server.");
Scanner scanner = new Scanner(System.in);
String userInput = null;
boolean quit = false;
do {
userInput = scanner.readLine();
if(userInput != null && userInput.equals("quit")) {
client.sendMessage(userInput);
} else {
quit = true;
}
} while(!quit);
}
Of course I just made this up but its just an example of once you have your class structure properly broken out and things where they should be it will be very easy to hook a GUI up.
The list could go on but bottom line is you need to take a hard look at what classes need to know what information and why. Break apart classes and make fields private and dont share information unless they need to be shared! Its important that you really think about reducing code coupling.
Any way enough rambling and onto the actual problem with your code: in ServerClientFrontEnd.main you have this snipplet:
new ServerClientFrontEnd().startClient();
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerClientFrontEnd().setVisible(true);
}
});
You are creating 2 instances of ServerClientFrontEnd, one that starts the client the other that shows the GUI. The one that shows the GUI is the one where you change the List of strings and the other list is always empty. To make it work change the snipplet to read:
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
ServerClientFrontEnd fontEnd = new ServerClientFrontEnd();
fontEnd.startClient();
fontEnd.setVisible(true);
}
});

Related

Java Sockets listener

Would it be appropriate to use a thread to get objects received by a socket's InputStream and then add them to a ConcurrentLinkedQueue so that they can be accessed from the main thread without blocking at the poll-input loop?
private Queue<Packet> packetQueue = new ConcurrentLinkedQueue<Packet>();
private ObjectInputStream fromServer; //this is the input stream of the server
public void startListening()
{
Thread listeningThread = new Thread()
{
public void run()
{
while(isConnected()) //check if the socket is connected to anything
{
try {
packetQueue.offer((Packet) fromServer.readObject()); //add packet to queue
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
listeningThread.start(); //start the thread
}
public Packet getNextPacket()
{
return packetQueue.poll(); //get the next packet in the queue
}
It depends on what you need to do with this object that you'll use in main thread.
If need sometime to process it or if it'll be used many times than you can put it in a queue or in another class that will hold this object for you, but if the time you need to process it is low you and you don't need this object further after processing you don't really need to use a queue.
About using the ConcurrentQueue depends too, you need order? you need guarantee synchronism between the read and the write?
You can use Asynchronous socket too to handle many clients and process in the same thread or even getting the objects from them and throwing in a queue to further process.
But "be appropriate" is hard to answer because depends on what you need to do with this objects and how you'll handle it.

Interfacing Swing with a thread other than a worker

I've built a simple client and server for a project, using a very basic text interface for testing and development (code demonstrating usage below).
The client library has an acceptMessage() method and a getMessage() method, which basically push messages into or pull messages out of a blockingQueue for input and output respectively (in the client this is implemented with put() and take() calls). One thread blocks on System.in and sends read lines to the client via acceptMessage whilst the other blocks on the client getMessage() method and echoes messages to System.out when they arrive. All very basic but it works okay.
Now that I've gotten my client library to work I'm trying to figure out how to integrate it into an application that uses a Swing GUI. So far I've not got much further than building a simple form in the interface building tool in Netbeans, with a text input box and a label. The idea is for the text input box to take the place of reading from system.in and the label to display what would have otherwise been written to system.out. By that point I'll have replicated my simple test app in Swing.
From what I understand, everything that interacts with a Swing GUI directly has to run in the Swing thread, but the client is built to run as its own thread. I don't think sending a message to acceptMessage() from the GUI will be terribly difficult (I think it involves setting up an ActionPerformed method that will read the contents of the input box and call acceptMessage() on the client, though I'm still trying to figure it out), but I have no idea how to go about getting responses back. I know I can't have the client invoke functionality in the GUI thread because of thread safety issues, and besides the client library is written in such a way as to not know anything about its consuming class. A client instance is simply passed into the consuming class which then uses acceptMessage() and getMessage() to send and receive messages. It does not (and should not) care what the consuming class actually is.
Is it possible with this architecture to easily integrate the client into the GUI? If so, what's the correct way of handling input from the client? (Like I said, I think output to the client isn't going to be especially difficult once I've figured out that aspect of Swing).
My primary motivation for using Swing is that a) it seems to be the best documented GUI library for Java, b) Netbeans already has tools for working with Swing and c) I have a rigid deadline and don't have time to switch GUI libraries and start from scratch (this is for a university project). Had I more time I'd have probably looked into other libraries, but I imagine they'd all have their own sets of quirks as well.
import java.io.*;
import java.util.logging.*;
public class TestApp implements Runnable {
private Client <String> client = null;
private UpstreamChannel upstream = null;
private DownstreamChannel downstream = null;
private Thread upstreamThread = null;
private Thread downstreamThread = null;
private boolean ending = false;
private class UpstreamChannel implements Runnable {
private TestApp outer = null;
#Override
public void run () {
Thread.currentThread ().setName ("TestApp.UpstreamChannel");
try (BufferedReader inReader = new BufferedReader (new InputStreamReader (System.in))) {
while (!this.outer.ending) {
this.outer.client.acceptMessage (inReader.readLine ());
}
} catch (IOException ex) {
Logger.getLogger (this.getClass ().getName ()).log (Level.SEVERE, ex.getMessage (), ex);
} finally {
this.outer.ending = true;
this.outer.downstreamThread.interrupt ();
Thread.currentThread ().interrupt ();
return;
}
}
public UpstreamChannel (TestApp app) {
this.outer = app;
}
}
private class DownstreamChannel implements Runnable {
private TestApp outer = null;
#Override
public void run () {
Thread.currentThread ().setName ("TestApp.DownstreamChannel");
try {
while (!this.outer.ending) {
System.out.println (this.outer.client.getMessage ());
}
} catch (InterruptedException ex) {
Logger.getLogger (this.getClass ().getName ()).log (Level.INFO, ex.getMessage (), ex);
} finally {
this.outer.ending = true;
this.outer.upstreamThread.interrupt ();
Thread.currentThread ().interrupt ();
return;
}
}
public DownstreamChannel (TestApp app) {
this.outer = app;
}
}
#Override
public void run () {
if ((null == this.upstreamThread)
&& (null == this.downstreamThread)) {
this.upstreamThread = new Thread (this.upstream);
this.downstreamThread = new Thread (this.downstream);
this.upstreamThread.start ();
this.downstreamThread.start ();
try {
this.upstreamThread.join ();
this.downstreamThread.join ();
} catch (InterruptedException ex) {
Logger.getLogger (this.getClass ().getName ()).log (Level.INFO, ex.getMessage (), ex);
} finally {
this.upstreamThread.interrupt ();
this.downstreamThread.interrupt ();
System.out.println ("Sayonara");
}
}
}
public TestApp (Client <String> client) {
this.upstream = new UpstreamChannel (this);
this.downstream = new DownstreamChannel (this);
this.client = client;
Logger.getLogger (this.getClass ().getName ()).log (Level.INFO, "Class instantiated");
}
}
The code for starting the client app is as follows:
public static void main (String[] args) throws UnknownHostException, IOException, InterruptedException {
Client <String> clientInstance = new Client ("localhost", 8113);
TestApp app = new TestApp (clientInstance);
Thread clientThread = new Thread (clientInstance);
Thread appThread = new Thread (app);
clientThread.start ();
appThread.start ();
clientThread.join ();
appThread.interrupt ();
System.exit (0);
}
}
EDIT: I thought a worker thread that polls getMessage (and therefore blocks until a message arrives) and uses publish() to make it available would be a solution, but I think there's a risk of messages getting "dropped on the floor" if two messages arrive in quick succession.
SwingWorker reader = new SwingWorker () {
#Override
protected Object doInBackground () throws Exception {
while (!this.isCancelled ()) {
publish (clientInstance.getMessage ());
}
return null;
}
};
So your basic problem is how to get
while (!this.outer.ending) {
System.out.println (this.outer.client.getMessage ());
}
to set the text on a label instead of printing to stdout. You're right that since this is a separate thread, you can't call a method directly on a GUI widget. But you can ask the GUI thread to dispatch some code that will get run in the GUI thread,
while (!this.outer.ending) {
final String message = this.outer.client.getMessage ();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
theLabel.setText(message);
}
});
}
The other way around might be as easy as having an event handler in your GUI call
this.outer.client.acceptMessage (textBox.getText());
However if acceptMessage is also a blocking call, you need a separate thread here as well, and have the GUI communicate the message over to that thread.
I personally like to follow something like this in your actionPerformed method:
public void actionPerformed( ActionEvent event ) {
Promise<SomeReturn> promise = server.acceptMessage( message, SomeReturn.class );
promise.onSuccess( new Callback() {
public void call( SomeReturn result ) {
// this is on the swing thread
someLabel.setText( result.getText() );
}
});
}
Then this is the promise class for asynchronous operations:
public class Promise<T> {
Callback<T> successCallback;
Callback<? extends Exception> errorCallback;
// swing client will register callbacks with these methods
public onSuccess( Callback<T> callback ) {
successCallback = callback;
}
// swing client will register callbacks with these methods
public Promise<T> onError( Callback<? extends Exception> callback ) {
errorCallback = callback;
}
// network client thread will call these methods when it gets a response
public void setResult( final T result ) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
if( successCallback != null )
successCallback.call( result );
else
log.warning("Response dropped! No success callback registered " + result );
}
});
}
// network client thread will call these methods when it gets a response
public void setError( final Exception ex ) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
if( errorCallback != null )
errorCallback.call( ex );
else
log.error( ex );
}
});
}
}
I don't like using something like getMessage() because that requires a synchronous style coding where the swing client has to poll or know when to call getMessage() so that it won't block the thread. Instead why not let the thread performing the work call you back when a response arrives. It does that by calling setResult() or setError() on the Promise it returned. You request another thread to perform an action by calling acceptMessage(), then it returns to you a Promise. You can register with that promise to be notified when that message is processed (either success or error).
In Java SE API we have Future which is really close to this idea of Promise, but unfortunately they didn't provide a callback mechanisms to be notified when the result arrives. It's tremendously disappointing the API authors didn't do that because the interface they created is pretty much useless.
Behind the acceptMessage() implementation could be lots of things. You could spin up a thread passing the message and promise to it to service that message, or you could drop the message + promise onto a queue that a consumer thread or thread pool draws from. When it finishes processing the message it uses the promise to call back to your UI.

Sockets with OSGi: Bundle stopped, socket still open

I'm facing this issue working with a ServerSocket inside one of my bundles, let's just call it: FooBundle.
This FooBundle has, among others, a SocketListener.java class. This class is a Thread and to make a little overview of it, I'll paste some pseudocode:
public class SocketListener implements Runnable{
ServerSocket providerSocket;
Socket connection = null;
private boolean closeIt = false;
public void run() {
try {
//Create the server socket
providerSocket = new ServerSocket(41000, 10);
} catch (IOException e1) {
//catching the exception....
}
while(!closeIt){
try{
connection = providerSocket.accept();
in = new Scanner(new InputStreamReader(onnection.getInputStream()));
while(in.hasNext() !=false)
message = message + " "+in.next();
// bla bla bla...
} catch (IOException e) {
//bla bla...
}
finally{
try{
if (message.equalsIgnoreCase("bye"))
providerSocket.close();
closeIt = true;
}
catch(IOException ioException){
//........
}
}
As you can see, it's a simple thread that waits for a connection until the message it receives from one of the SocketClients is "bye".
This is the problem I'm facing right now: When the Bundle is stopped, I do need to restart the entire OSGi framework : If I try to restart the bundle, a java.net.BindException message is thrown: "Address already in use". So, I stopped the bundle but the socket hasn't been closed.
In OSGi, you need to take care of what the stop() method inside the Activator must include, but I just can't pass any reference of an anonymous thread to the Activator.
Imagine that this is my class diagram inside the bundle:
**FooBundle**
|__FooBundleActivator
|__FooImpl
|__SocketListener (thread)
The SocketListener thread is called from the FooImpl class as an anonymous thread.
My question is: Is there any appropiate method to have such control of anonymous threads and specifically in my case, of non-closing socket ports, inside the OSGi paradigm?
Thanks in advance.
If your bundle is told to stop then assume the guy doing the stopping knows what he is doing. Yes, your protocol expects the 'bye' but shit happens, any protocol that has problems with these things is too fragile for the real world. In general, all your tasks in OSGi should have a life cycle. So this would be my code (using DS instead of activators).
#Component
public class ProtocolServer extends Thread {
volatile ServerSocket server;
volatile Socket connection;
public ProtocolServer() {
super("Protocol Server on 4100"); // to identify the thread
}
#Activate void activate() {
setDaemon(true);
start();
}
#Deactivate void deactivate() {
interrupt();
// best effort close (even if null)
try { server.close(); } catch(Exception e) {}
try { connection.close(); } catch(Exception e) {}
join(10000); // waits 10 secs until thread exits
}
public void run() {
// loop for active component
while( !isInterrupted() )
try {
doServer();
} catch( Exception e) {
log(e);
// bad error, accept failed or bind failed
// or server socket was closed. If we should remain
// active, sleep to prevent overloading the
// system by trying too often, so sleep
if ( !isInterrupted() )
try { Thread.sleep(5000); } catch(Exception e) {}
}
}
private void doServer() throws Exception {
server = new ServerSocket(4100)
try {
while( !isInterrupted() )
doConnection(server);
} finally {
server.close();
}
}
private void doConnection(ServerSocket server) throws Exception {
connection = server.accept();
try {
doMessages(connection);
// the pseudo code exits here, but that seems
// kind of weird? If desired, interrupt
// this object, this will exit the thread
} catch( Exception e) {
log(e); // the connection failed, is not uncommon
} finally {
connection.close();
connection = null;
}
}
private void doMessages(Socket connection) {
MyScanner s = new MyScanner(socket);
String msg;
while( !isInterrupted() && !"bye".equals( msg=s.getMessage()))
process(msg);
}
}
One important design consideration in OSGi is that the components keep working even if there are failures. In a network you often have transient errors that go away on their own. Even if they don't it is desirable that the server keeps on trying while you fix the problem. Your pseudo code would be a nightmare in practice since it would disappear on any error. Any system with multiple such components tends to becomes quickly unstable.
One thing that also surprised me is that you only support one connection at a time. In general it is better to not limit this and handle the messages in their own thread. In that case, you must ensure that each created handler for a connection is also closed appropriately.
Instantiate the ServerSocket outside (probably in the Activator) and pass it to the SocketListener via a constructor. You can call serverSocket.stop() in the stop function of the Activator than.
In case you call ServerSocket.stop() a SocketException will be thrown that is a subclass of IOException. Please think of handling IOException in the while iteration in the way that it will stop executing the iteration for sure.
You need to close that listening socket regardless of the message before exiting the thread function. Then what should really make a difference for you is calling setReuseAddress(true) on that socket to allow binding the port while old connection hangs in the timeout state.
And, please please please, use better indentation technique in your code ...

Components I used to draw a form won't appear after compile

I'm trying to create a chat program in java but I had a problem when I run the server form, that the components I used to draw won't appear.
this is the code I used in the run of the form :
public void run() {
Server s = new Server();
s.setVisible(true);
// Etablir la connexion
try
{
ServerSocket ecoute;
ecoute = new ServerSocket(1111);
Socket service = null;
System.out.println("Serveur en attente d'un client !");
while(true)
{
service = ecoute.accept();
System.out.println("Client connécté !");
DataInputStream is = new DataInputStream(service.getInputStream());
s.jTextArea1.setText("Client dit : " + is.readUTF().toUpperCase());
service.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
You said nothing happens when this code is ran. The presence of a public void run() method tells me that this is a thread, or at least a Runnable.
Because of the while(true), if this thread is not started in the proper manner, it will not run independently; that is it will hold up the entire program.
Instead of calling thread.run();, call thread.start();. This will call the run method for you, after starting a new thread that will run in parallel to the main thread.
If this code is not in a thread, and you just used public void run() by chance, then it will still provide the same problem for you.
For more information, refer to the Documentation on Threads

How to stop ServerSocket Thread correctly? Close Socket failed

I know this has been discussed some times before, but I can't find an appropriate solution for my problem. I want to run a ServerSocket thread in the background, listening to the specified port. It's working actually, but only once. Seems that the port the server is listening to is never closed correctly and still active when I try to restart (O don't restart the thread itself). Can some tell why it is not working correctly? Thanks in advance for any help...!
edit:
I have same problem on the client side. I have a sender thread and also that one cannot not be stopped. What is the best way to do that?
The ClientConnector is just a class which connects to the server port and sends the data.
It's not a thread or anything like that.
That's my sender class:
private class InternalCamSender extends Thread {
private int sendInterval = 500; // default 500 ms
private ClientConnector clientConn = null;
public InternalCamSender() {
this.sendInterval = getSendingInterval();
this.clientConn = new ClientConnector();
}
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
clientConn.sendCamPdu(CodingScheme.BER, createNewPDU());
try {
Thread.sleep(sendInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And I try to handle it's behaviour like that:
if(jButton_startSending.getText().equals(STARTSENDING)) {
new Thread() {
public void run() {
iSender = new InternalCamSender();
iSender.start();
jButton_startSending.setText(STOPSENDING);
}
}.start();
} else {
new Thread() {
public void run() {
if(iSender.isAlive()) {
iSender.interrupt();
try {
iSender.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
iSender = null;
jButton_startSending.setText(STARTSENDING);
}
}.start();
}
Somehow I cannot stop the InternalCamSender like that. I tried with a volatile boolean before, was the same. I read the http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html page and tried also the example What should I use instead of Thread.stop? but even that was not stopping the thread? I am lost.
Any ideas?
edit:
found the answer for my clinet sending problem here http://www.petanews.de/code-snippets/java/java-threads-sauber-beenden-ohne-stop/
even i don't know why that is working. I am sure I tried that way before.
Problem solved!
You should close your resources (the streams and socket) in a finally block, rather than a catch block - this way the resources are always closed, whether an exception is caught or not.
It's also a bad practice to call System.exit() from within a catch block or within a thread - you are forcibly shutting down the whole JVM on any instance of an error. This is likely the cause of your problem with the server socket as well - whenever any exception is encountered with reading/closing the streams, you are exiting the JVM before you have a chance to close the server socket.

Categories

Resources