Java: Multithreading with two different input sources and reacting - java

First question here on StackOverflow, so please excuse me if I ask this incorrectly.
Basically, I'm writing a Multicast Client that indefinitely listens to a multicast address until the user types "quit" into the console. I've found that setting SO_TIMEOUT for the MulticastSocket, checking if "quit" has been typed, and then returning to the receive method call doesn't really work since a packet could be sent right after the timeout and the check of the console blocks. So I believe the best option is to simply have 2 threads going where one listens on the socket and blocks until it receives something, and the other thread listens to the console until told to quit. The only issue I have is that I'm unsure of how to go about having the console listening thread tell the socket thread to close the socket and terminate. System.end() would work but I fear that I'd leave a socket open, etc.
TLDR; Is there a way for the main method of a class to start a thread, and then respond a specific way once that thread ends? I need to listen to the console on one thread and a MulticastSocket on another, or just in the main of the client class.
Thanks everyone.

I would call Socket.close() to close the socket. This will produce an IOException in that thread. so before doing this I would set a flag like closed = true; and have the other thread check this before printing the error i.e. don't print an IOException if you have been closed. Something like this.
public class SocketListener implements Runnable, Closeable {
final MulticastSocket socket;
final Consumer<DatagramPacket> packetConsumer;
volatile boolean closed;
public SocketListener(MulticastSocket socket, Consumer<DatagramPacket> packetConsumer) {
this.socket = socket;
this.packetConsumer = packetConsumer;
}
#Override
public void run() {
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
try {
while(!closed) {
socket.receive(packet);
packetConsumer.accept(packet);
}
} catch (IOException e) {
if (!closed)
e.printStackTrace();
}
}
#Override
public void close() throws IOException {
closed = true;
socket.close();
}
}
for example, in your main thread you can do
MulticastSocket socket = ...
Consumer<DatagramPacket> packetConsumer = ...
try (SocketListener listener = new SocketListener(socket, packetConsumer)) {
boolean finished = false;
do {
// read from the console
if (some condition)
finished = true;
} while(!finished);
} // calls close() for you.

Related

Concurency at a thread pool in Java

I face this problem in Java.
I have a server class named MyServer and I want to implement a thread pool where each thread runs a method of MyServer when a request comes. I have created another class that implements a server pool named MultiThreadedSocketServer. The class is this:
public class MultiThreadedSocketServer {
public void startServer(MyServer s, int localport, int threadPoolSize) {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(threadPoolSize);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(localport);
System.out.println("Waiting for clients to connect...");
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool.submit(new ClientTask(clientSocket, s));
}
} catch (IOException e) {
System.err.println("Unable to process client request");
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
}
the class named MultiThreadedSocketServer has an argument named Server s which passes it in client Task class which a thread is created. The client task class is this:
class ClientTask implements Runnable {
private final Socket clientSocket;
private MyServer s;
public ClientTask(Socket clientSocket, MyServer s) {
this.s = s;
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Got a client !");
String inputLine = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Do whatever required to process the client's request
inputLine = in.readLine();
if (inputLine.equals("Bye")) {
System.out.println("Bye");
System.exit(0);
}
s.handleRequest(inputLine);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
As you can see when a request comes the handleRequest method of class MyServer is invoked. I want to make this method to run synchronized, meaning only one thread at a time to be able to run this method. Adding synchronized before the method implementation does not achieve anything.
Can anybody give me the proper way to do this?
Thanks in advance for your time.
PS: I added the whole code
MyServer Class
http://pastebin.com/6i2bn5jj
Multithreaded server Class
http://pastebin.com/hzfLJbCS
As it is evident in main I create three requests with handleRequest with arguments Task, task2 and Bye.
The correct output would be
Waiting for clients to connect...
Got a client !
This is an input Task
Request for Task
Got a client !
This is an input task2
Request for task2
Got a client !
This is an input
Bye
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
You say that you want the server to handle requests in order. This is hard to ensure because you are opening up 3 sockets and writing them to the server but not waiting for any response. This is implementation dependent but I'm not sure there is any guarantee that when the client returns from doing a socket InputStream write, that the server has received the bytes. This means that from the client side, there is no guarantee that the IO completes in the order that you want.
To see if this is the problem, I would remove the System.exit(0) to see if the other lines make it, just after the "Bye" string does. Or you could put a Thread.sleep(5000); before the exit(0).
A simple sort-of fix would be to make sure your PrintStream has auto-flush turned on. That at least will call flush on the socket but even then there are race conditions between the client and the server. If the auto-flush doesn't work then I'd have your client wait for a response from the server. So then the first client would write the first command and wait for the acknowledgement before going to the 2nd command.
In terms of your original question, locking on the server wouldn't help because of the race conditions. The "Bye" might make it first and lock the server fine.
These sorts of questions around how to synchronize the threads in a multi-threaded program really make no sense to me. The whole point of threads is that they run asynchronously in parallel and don't have to operate in any particular order. The more that you force your program to spit out the output in a particular order, the more you are arguing for writing this without any threads.
Hope this helps.
If the problem is that the bye message kills the server before other requests can be handled, one solution could be to not call System.exit(0); on bye.
The bye message could set a flag block further requests from being handled and also notify some other mechanism to call System.exit(0); when the thread pool is idle with no requests left to handle.

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

Socket.close() have no effect during Socket.connect()

Using the default socket implementation on Windows, I was not able to find any effective method to stop Socket.connect(). This answer suggests Thread.interrupt() will not work, but Socket.close() will. However, in my trial, the latter didn't work either.
My goal is to terminate the application quickly and cleanly (i.e. clean up work needs to be done after the socket termination). I do not want to use the timeout in Socket.connect() because the process can be killed before a reasonable timeout has expired.
import java.net.InetSocketAddress;
import java.net.Socket;
public class ComTest {
static Socket s;
static Thread t;
public static void main(String[] args) throws Exception {
s = new Socket();
InetSocketAddress addr = new InetSocketAddress("10.1.1.1", 11);
p(addr);
t = Thread.currentThread();
(new Thread() {
#Override
public void run() {
try {
sleep(4000);
p("Closing...");
s.close();
p("Closed");
t.interrupt();
p("Interrupted");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
s.connect(addr);
}
static void p(Object o) {
System.out.println(o);
}
}
Output:
/10.1.1.1:11
Closing...
Closed
Interrupted
(A few seconds later)
Exception in thread "main" java.net.SocketException: Socket operation on nonsocket: connect
You fork the thread and then the main thread is trying to make the connection to the remote server. The socket is not yet connected so I suspect s.close() does nothing on a socket that is not connected. It's hard to see what the INET socket implementation does here. t.interrupt(); won't work because the connect(...) is not interruptible.
You could use the NIO SocketChannel.connect(...) which looks to be interruptible. Maybe something like:
SocketChannel sc = SocketChannel.open();
// this can be interrupted
boolean connected = sc.connect(t.address);
Not sure if that would help though.

Java.nio.channels.ServerSocketChannel - accept() memory leak

I got thread for server in my Android app and need to handle it properly when user decide to close it. I choose non-blocking ServerSocketChannel which accept() clients.
And got this
public class SocketServer extends Thread
{
private static final String LOG_TAG = "SocketServer";
private boolean isRunning = false;
private ServerSocketChannel listener = null;
public void _stop()
{
this.isRunning = false;
}
public void _start()
{
this.isRunning = true;
this.start();
}
private void free()
{
try
{
listener.close();
}
catch (IOException e)
{
//Error handle
}
listener = null;
}
public SocketServer(int port)
{
super();
try
{
listener = ServerSocketChannel.open();
listener.configureBlocking(false);
listener.socket().bind(new InetSocketAddress(port));
}
catch (IOException e)
{
//Error handle
}
}
public void run()
{
SocketChannel client = null;
while(isRunning)
{
try
{
client = listener.accept();//GC going mad
}
if(client != null)
Log.i(LOG_TAG, "ACCEPTED CLIENT");
catch (IOException e)
{
//Error handle
}
}
free();
}
All i'm doing is accepting new client - getting null because of no incoming connections and do it again until server is stopped.
ServerClient client is null at start and assigned to null by accept() if no connections available.
But Java's garbage collector thinks what client is somehow init by accept() or accept() somehow allocate some memory, which GC cleans after every while loop.
If comment accept() line (e.g do nothing) where will be no GC at all, so problem exactly in accept().
This quite not right in my opinion.
P.S. If there is some way to break blocking ServerSocket accept()/Socket read() state and exit properly, please tell me.
P.S. 2 Is it safe to write/ read to SocketChannel socket() as to Socket, will it block thread?
Many operations in Java create temporary objects internally to do their work.
You are much better off using a blocking SocketServer. This way the objects it creates is only on a per-accepted-Socket basis rather than a per-attempt basis.
I suggest you implement blocking NIO with a thread (or two) per connection first. If then you discover you have a performance issue with the number of threads you have, try using a Selector with non-blocking NIO.

how does a multi-threaded server work?

I've got from someone this example with a multithreaded server on android:
http://tutorials.jenkov.com/java-multithreaded-servers/singlethreaded-server.html
But I have a few difficulties in understanding a part of the code:
while(! isStopped()) {
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException("Error accepting client connection", e);
}
What I don't understand is, what happens when I have an exception at this line:
clientSocket = this.serverSocket.accept();
From what I can tell is that this function gets called:
private synchronized boolean isStopped() {
return this.isStopped;
}
But how it gets to close that socket? Cause if u get exception in the attempt to accept a client you should close the socket returned by accept.
I assume that this is done in here:
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
But where is stop() called,how it gets to make the connection between isStopped() and onStop()....And what is with that "synchronized"?
Hope I've been clear with my unclarities! Thank u in advance:)
You've probably moved on but for posterity...
what happens when I have an exception at this line
clientSocket = this.serverSocket.accept();
If you get an exception inside of accept then no socket is returned so there is nothing to close. Either accept() returns a valid socket that you should handle and then close or it throws an exception. Never both.
where is stop() called?
Stop looks to be called from the outside world by some caller that wants to shutdown the server socket. With a server, you create a server-socket and then you accept individual connections to remote clients, which returns a socket for that client. Each of the client handlers need to close their own individual connections. When the server is shutting down (in this case when stop() is called), the server-socket is then closed.
Once stop() is called then the server socket is closed and the accept() method will throw an exception. That's why there is a if(isStopped()) check in the code to avoid throwing an exception.
how it gets to make the connection between isStopped() and onStop()
isStopped() is a private method that tests to see if someone has called the stop() method. I assume onStop() is an Android method? They are not related although someone might want to call singleThreadedServer.stop() inside of onStop().
what is with that synchronized?
The synchronized keyword is used by multithreaded programs as a mutex and memory barrier. It only allows 1 thread to be executing inside of the synchronized block at one time. It also makes sure that all of the local variables are synced between the threads and central memory. See the java docs:
http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Having that private method be synchronized is really gross IMO. I assume this is being done to make sure isStopped has been updated. I would have used a volatile boolean or AtomicBoolean instead.

Categories

Resources