how does a multi-threaded server work? - java

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.

Related

Java: Multithreading with two different input sources and reacting

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.

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

How can I close the socket in a proper way? [duplicate]

This question already has an answer here:
Proper way to close an AutoCloseable
(1 answer)
Closed 3 years ago.
This is a simple TCP server. How can i close the socket when the program is terminated?
I have using try/finally and try to close the socket. But it doesn't run the finally block when I exit the program.
Anyone can have idea on how to close the socket in a proper way?
try {
socket = new ServerSocket(port);
System.out.println("Server is starting on port " + port + " ...");
}catch (IOException e){
System.out.println("Error on socket creation!");
}
Socket connectionSocket = null;
try{
while(true){
try{
connectionSocket = socket.accept();
Thread t = new Thread(new ClientConnection(connectionSocket));
t.start();
}catch (IOException e) {
System.out.println("Error on accept socket!");
}
}
}finally{
this.socket.close();
System.out.println("The server is shut down!");
}
After creating your ServerSocket, you could add a ShutdownHook to close it on JVM termination, something like this:
Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){
try {
socket.close();
System.out.println("The server is shut down!");
} catch (IOException e) { /* failed */ }
}});
Invoking ServerSocket#close will terminate the blocking ServerSocket.accept call, causing it to throw a SocketException. However, note that your current handling of IOException in the while loop means you will then re-enter the while loop to attempt accept on a closed socket. The JVM will still terminate, but it's a bit untidy.
Shutdown hooks do not run if you terminate a console application in Eclipse (on Windows at least). But they do run if you CTRL-C Java in a normal console. For them to run, you need the JVM to be terminated normally, e.g. SIGINT or SIGTERM rather than SIGKILL (kill -9).
A simple program which you can execute in Eclipse or a console will demonstrate this.
public class Test implements Runnable {
public static void main(String[] args) throws InterruptedException {
final Test test = new Test();
Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){
test.shutdown();
}});
Thread t = new Thread(test);
t.start();
}
public void run() {
synchronized(this) {
try {
System.err.println("running");
wait();
} catch (InterruptedException e) {}
}
}
public void shutdown() {
System.err.println("shutdown");
}
}
No need in your particular case, the operating system will close all the TCP sockets for you when the program exits.
From javadoc :
The Java runtime automatically closes the input and output streams,
the client socket, and the server socket because they have been
created in the try-with-resources statement.
Also
The finalize() method is called by the Java virtual machine (JVM)
before the program exits to give the program a chance to clean up and
release resources. Multi-threaded programs should close all Files and
Sockets they use before exiting so they do not face resource
starvation. The call to server.close() in the finalize() method closes
the Socket connection used by each thread in this program.
protected void finalize(){
//Objects created in run method are finalized when
//program terminates and thread exits
try{
server.close();
} catch (IOException e) {
System.out.println("Could not close socket");
System.exit(-1);
}
}
Howcome the finally is not run? Probably the while(true) should be replaced with something like
while (!shutdownRequested)
alternatively you can create a shutdown hook that handles the socket close
Well, how do you "exit" the program? finally will be executed if an exception will be thrown or if the try block finishes its execution in a "normal" way but I think that might be "hard" because of your while(true).
To close the socket you should use socket.close() and I would recommend you not to rely on the destroy function.

Listening for connections in a separate thread

This is part of a messenger project in java. Because clients use direct connections to chat, I want eavry client to listen on some port, and others to make a socket to that address. but when i call ServerSocket.accept() in another thread it appears that all threads have been suspended. which means nothings happens after executing that command. Here is the code which makes new thread.
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
while(true){
System.out.println("flag1");
Socket socket = listeningSocket.accept();
System.out.println("flag2");
new Chat(socket).setVisible(true);;
jTextArea1.append("successfully connected\n");
}
} catch (NullPointerException e) {
System.out.println("i know");
}
catch (IOException e) {
e.printStackTrace();
jTextArea1.append("error in recieving connection\n");
}
}
});
any ideas how to solve this?
when i call ServerSocket.accept() in another thread it appears that
all threads have been suspended
Appears how? accept() only blocks the current thread. Are you calling it in the AWT thread? e.g. an actionPerformed() method? Don't do any network operations in those methods, use separate threads.
Socket.accept() DOES block the CURRENT thread. You'll see "flag2" printed only after a connection is received. But it blocks only CURRENT thread.
I suspect you are not running the separate thread correctly (you're calling yourThreadHere.start(), not .run(), right?).

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