Java Sockets listener - java

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.

Related

Read and write from a socket simultaneously

I'm writing an android app in java and I want to create a listener that receive messages in a while(true) loop, and also to be able to send messages to the server.
For this task I'm using sockets with asyncTask.
I have written a connectionHandler class which handle all the send and receive requests for my app.
So far so good, everything is working fluently for just sending and receiving messages one at a time, but I just couldn't find a way to do it simultaneously.
I need to execute the following code in a thread, but I don't know how to do it, because I have to return a String:
public static String receive() {
try {
return mConnectionHandler.new AsyncReceiveFromServer().execute()
.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
private class AsyncReceiveFromServer extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String result = null;
try {
result = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
When I'm running the receive function in a while(true) loop, I can't send messages, because the ...execute().get() is blocking the java class connectionHandler.
So to sum up, how can I execute the above code in a thread or any other asynchronous way?
Or maybe you have any other suggestion to run the send and receive simultaneously while the receive is a while(true) loop?
First off- never use execute.get(). If you think you need to use it, you're architected wrong- it breaks the entire point of using a thread to have the calling thread wait for a result. If you just call execute, you'll run on another thread and work fine. If you need more than 1 thread running truly simultaneously, use executeOnExecutor() to override the 4.0 shared thread pool mechanism of AsyncTask.
Or better yet- don't use AsyncTask for this. You have something you want to run forever, waiting for input from a remote connection. This is a better fit for a Thread than an AsyncTask. I'd go with a thread and have the while loop built into the thread, and have the thread terminate only when the connection is closed.

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 ...

Get messages from thread

In First class have method "listen" which listening client socket
public void listen() throws IOException {
while (true) {
socket = this.serverSocket.accept();
DataOutputStream out = new DataOutputStream( socket.getOutputStream() );
this.outputStreams.put(socket, out);
Thread miltiServer;
miltiServer = new Thread() {
#Override
public void run() {
InputStream sin = null;
try {
sin = socket.getInputStream();
ObjectInputStream in = new ObjectInputStream(sin);
message = (AgentData) in.readObject();
} catch (ClassNotFoundException ex) {
} catch (IOException ex) {
}
}
};
miltiServer.start();
}
In Second class i need to read and analyze messages which recieved from client socket. I don't know how to get messages in other class. I have idea to use Callable interface, but if i use it, return statement will exit from infinitive cycle.
An easy way for your socket listener to communicate the messages to your Second class is through a BlockingQueue. The listener would read from the socket input stream and call queue.put(...) to add any messages to the queue.
Then the Second class would be in a loop calling queue.take(); which would return each message when it is added to the queue. If you want unlimited messages to be queued then LinkedBlockingQueue would work. If you want to throttle the messages then a bounded queue such as ArrayBlockingQueue might be more appropriate.
Both threads would need to share the same BlockingQueue so you will need to construct it and pass it to both threads or put a method on your Second class named something like addMessage(...) and the BlockingQueue would be inside of your Second class. Then the listener would call second.addMessage(...);.

Read lines from Socket and put each into BlockingQueue

Can anyone provide examples in Java, or advise about implementing a class which asynchronously reads lines from a socket and puts each line into a BlockingQueue. Assume the socket is connected, and the BlockingQueue and consumer already exists.
Edit: One more thing, it needs to have the ability to timeout after a period of inactivity, and stop immediately on command.
It's not homework, I simply have not been able to find complete examples for how to do this well, and reliably.
Thank you very much.
You sound like you've already done the work, to be honest. All you need to do is create a BlockingQueue and have a thread to process it which is your consumer I guess. Assuming you have a DataInputStream 'in'...
Something like this:
BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<String>();
public void run()
{
while (true)
{
try
{
receivedQueue.put(in.readUTF());
} catch (EOFException e)
{
ch.getClient().disconnect();
break;
} catch (IOException e)
{
break;
} catch (InterruptedException e)
{
break;
}
}
theQueueProcessor.interrupt();
}

Can I invoke XMPPConnection.sendPacket from concurrent threads?

Motivation
I want extra eyes to confirm that I am able to call this method XMPPConnection.sendPacket(
Packet ) concurrently. For my current code, I am invoking a List of Callables (max 3) in a serial fashion. Each Callable sends/receives XMPP packets on the one piece of XMPPConnection. I plan to parallelize these Callables by spinning off multiple threads & each Callable will invoke sendPacket on the shared XMPPConnection without synchronization.
XMPPConnection
class XMPPConnection
{
private boolean connected = false;
public boolean isConnected()
{
return connected;
}
PacketWriter packetWriter;
public void sendPacket( Packet packet )
{
if (!isConnected())
throw new IllegalStateException("Not connected to server.");
if (packet == null)
throw new NullPointerException("Packet is null.");
packetWriter.sendPacket(packet);
}
}
PacketWriter
class PacketWriter
{
public void sendPacket(Packet packet)
{
if (!done) {
// Invoke interceptors for the new packet
// that is about to be sent. Interceptors
// may modify the content of the packet.
processInterceptors(packet);
try {
queue.put(packet);
}
catch (InterruptedException ie) {
ie.printStackTrace();
return;
}
synchronized (queue) {
queue.notifyAll();
}
// Process packet writer listeners. Note that we're
// using the sending thread so it's expected that
// listeners are fast.
processListeners(packet);
}
protected PacketWriter( XMPPConnection connection )
{
this.queue = new ArrayBlockingQueue<Packet>(500, true);
this.connection = connection;
init();
}
}
What I conclude
Since the PacketWriter is using a BlockingQueue, there is no problem with my intention to invoke sendPacket from multiple threads. Am I correct ?
Yes you can send packets from different threads without any problems.
The Smack blocking queue is because what you can't do is let the different threads write the output stream at the same time. Smack takes the responsibility of synchronizing the output stream by writing it with a per packet granularity.
The pattern implemented by Smack is simply a typical producer/consumer concurrency pattern. You may have several producers (your threads) and only one consumer (the Smack's PacketWriter running in it's own thread).
Regards.
You haven't provided enough information here.
We don't know how the following are implemented:
processInterceptors
processListeners
Who reads / writes the 'done' variable? If one thread sets it to true, then all the other threads will silently fail.
From a quick glance, this doesn't look thread safe, but there's no way to tell for sure from what you've posted.
Other issues:
Why is PacketWriter a class member of XMPPConnectionwhen it's only used in one method?
Why does PacketWriter have a XMPPConnection member var and not use it?
You might consider using a BlockingQueue if you can restrict to Java 5+.
From the Java API docs, with a minor change to use ArrayBlockingQueue:
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new ArrayBlockingQueue();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
For your usage you'd have your real sender (holder of the actual connection) be the Consumer, and packet preparers/senders be the producers.
An interesting additional thought is that you could use a PriorityBlockingQueue to allow flash override XMPP packets that are sent before any other waiting packets.
Also, Glen's points on the design are good points. You might want to take a look at the Smack API (http://www.igniterealtime.org/projects/smack/) rather than creating your own.

Categories

Resources