I have some questions about the UnicastRemoteObject class.
take the following code:
public class MaxImpl extends UnicastRemoteObject implements Max{
public MaxImpl () throws RemoteException {}
#Override
public int getMax(int[] A) throws RemoteException {
// ...
return max;
}
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099);
MaxImpl max = new MaxImpl();
Naming.rebind("maximum", max);
} catch (RemoteException ex) {
System.out.println(ex.getMessage());
} catch (MalformedURLException ex) {
System.out.println(ex.getMessage());
}
}
}
what does the following statement do:
MaxImpl max = new MaxImpl();
generate a stub.
generate a stub and create a remote object so that it can receive
invocations of its remote methods from remote clients.
the above code is executed indefinitely, Why? I suppose there's a loop:
while(true){ ServerSocket server = ...; }
generate a stub.
No.
generate a stub and create a remote object so that it can receive invocations of its remote methods from remote clients.
No.
It exports the remote object, which consists of:
Open a ServerSocket
Start a thread listening at that socket.
Create a stub object containing the IP address, the port used at (1), and a remote object identifier.
Note that (1( and (2) Can be shared between remote objects using the same port so it may not happen precisely as above.
Now the existence of the thread at (2) will prevent the JVM from exiting.
Related
public class Slave implements Runnable {
public ServerSocket slaveSocket;
public Slave(ServerSocket sk) {socket = sk;}
#Override
public void run() {
Socket client = slaveSocket.accept(); // slave will wait to serve a client
// more code...
Socket clientPart2 = slaveSocket.accept();
// more code...
}
}
public class Server {
public static void main(String[] args) {
// for example only, incomplete code
ServerSocket serverSocket = new ServerSocket(0); // a client connect to 8088
Slave slave = new Slave(serverSocket);
new Thread(slave).start(); // slave serve the current client, the server wait for new client
// send new slave's port to client ...
}
}
So I have a server that serves multiple clients at once. Whenever a client connects, the server will create a new Slave, send the IP/port of that slave to the client, then the client will work with the slave.
However, if the client receives the slave's address then do nothing (or quit) (Edit: it means the client and server are connected but the client do nothing, because for example the user goes for lunch) slaveSocket.accept() causes that slave Thread to run forever, which is wasteful.
I want the slave thread to exit after 30 second of waiting for slaveSocket.accept(). Since slaveSocket.accept() is blocking, I cannot do that from inside the void run().
What is the correct, clean way to solve this problem? Thank you.
Edit 1: a ServerSocket is passed to the slave because the client can have multiple processes that will connect to that slave. So it doesn't just perform one function.
If you set a timeout with setSoTimeout and no client connects, ServerSocket.accept will throw an exception. You can catch this exception.
To set a timeout of 30 seconds, use:
serverSocket.setSoTimeout(30000)
Non-blocking I/O:
Take a look at AsynchronousServerSocketChannel's accept method which returns a Future. Then the Future has a getter with timeout which can do what you are asking.
Note: you may read a related tutorial.
Then the getter will return an AsynchronousSocketChannel which can be converted back to blocking via the corresponding Channels.newInputStream and Channels.newOutputStream methods to be used with the blocking approach in the worker threads.
Blocking I/O:
I think you actually meant on how to implement a server which accepts clients sequentially and serves them in parallel, with blocking I/O. If that is the case, then you may take a look at the following example:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;
public class Main {
public static class Worker implements Runnable {
private final Socket sck;
private OutputStream os;
private InputStream is;
public Worker(final Socket sck) {
this.sck = Objects.requireNonNull(sck);
}
#Override
public void run() {
try {
os = sck.getOutputStream();
is = sck.getInputStream();
//ALL the work with the client goes here, unless you need more than one connections with him.
}
catch (final IOException iox) {
System.err.println(iox);
}
finally {
try { is.close(); } catch (final IOException | RuntimeException x) {}
try { os.close(); } catch (final IOException | RuntimeException x) {}
try { sck.close(); } catch (final IOException | RuntimeException x) {}
}
}
}
public static void main(final String[] args) {
ServerSocket srv = null;
try {
srv = new ServerSocket(8088);
while (true)
new Thread(new Worker(srv.accept())).start();
}
catch (final IOException iox) {
System.err.println(iox);
}
finally {
try { srv.close(); } catch (final IOException | RuntimeException x) {}
}
}
}
I have a problem with my Java RMI chat (client-server type) in which clients can "subscribe to the server", meaning all client refs are stored in an ArrayList on the server, all clients can access to specific commands and one client in turn can be a "special" client.
All commands respond in a different way depending if a client is the "special" or not (simply the server chooses one client and target it as "special" storing his reference in the ArrayList as normal and plus in a variable called active), in particular I have a problem with the command !quit:
If a special client calls the cmd !quit, he calls the remote method on the server siesce(Client reference) and then the server removes ALL REFERENCES of ALL CLIENTS from the ArrayList and calls back the abbandona() on ALL CLIENTS after which they should stop their execution.
Client Implementation variables
public class ClientImpl extends UnicastRemoteObject implements Client {
...
private static Server server; //reference to server
private static ClientImpl client; //reference to client object (it-self)
...
Client Method abbandona()
public void abbandona() throws RemoteException {
System.out.println("Sei stato espulso dalla chat");
System.exit(0);
}
Client main
Client inserts cmd !quit that calls this portion of code
//start of main and objects creations
...
try {
server.siesce(client);
} catch (RemoteException e) {
System.out.println("Esco...");
System.exit(1);
}
//end of main
Server Implementation variables
public class ServerImpl extends UnicastRemoteObject implements Server{
...
private static ArrayList<Persona> cli = new ArrayList<Persona>();
//the Persona object is a wrapper that contains a Client reference and a boolean
//the client can be taken by calling getCli()
...
private static Client active; //reference to SPECIAL client
Server method siesce(Client ref)
public synchronized void siesce(Client ref) throws RemoteException {
if (ref.equals(active)) { //checks if the SPECIAL client called this method
for (int i=0; i<cli.size(); i++) {
try {
cli.get(i).getCli().abbandona();
logger.info("...");
} catch (RemoteException e) {
logger.severe("...");
}
}
cli.clear(); //variables reset
count = 0;
guard = 0;
active = null;
ready = false;
}
else { //this else is used when a normal client calls this method
...
}
}
...
The problem is the fact that in the loop that checks all ArrayList elements after the first cli.get(i).getCli().abbandona() is called on the first element it launches the RemoteException (because the client quits) which is caught in the MAIN code of the client and not in the try catch in the for loop and this stops the method from continue doing this on other elements, so only the first client quits when the others don't.
How can achieve to let all clients stop their execution?
The client shouldn't exit inside the callback. Instead it should just (a) unexport itself and (b) post a Boolean somewhere that will tell the main thread to exit, after a couple of seconds to allow the callback to complete.
Im using this code:
final int LOCK_PORT= 54321;
ServerSocket ss = new ServerSocket(LOCK_PORT);
The thing is that in the same port you cannot listen to 2 different applications (teachers theory).
This code was implemented into an application and the same instance ran more than 1 time. The objective is that the same instance is not suposed to run more than 1 time in the same port. However this isnt working and it does run...
// Edited, more code...
public VentanaPropiedades() {
initFirst();
initComponents(); //graphic components of Matisse
}
private void initFirst() {
loadProperties(); //just internal values of the program, nothing to do
activateInstance();
}
private void activateInstance() throws Exception {
try {
final int LOCK_PORT= 54321;
ServerSocket ss = new ServerSocket(LOCK_PORT);
} catch (Exception e) {
System.out.println(e);
throw e;
}
}
private void killProgram() {
setVisible(false);
dispose();
System.exit(0);
}
private void validateInstance() {
try {
activateInstance();
} catch (Exception ex) {
killProgram();
}
}
--------------------------Supposed Solution---------------------------
The error catched when the 2nd instance DOES NOT RUN is this one:
java.net.BindException: Address already in use: JVM_Bind
However, this error not always happens and you can run more than 1 instance of the same program.
It doesn't work. You should get a BindException the second time you try to create the
socket. See if you accidentally catch it somewhere or if the port actually is different
or something similar.
The ServerSocket must be declared outside the method, right after main:
public class VentanaPropiedades extends javax.swing.JFrame {
ServerSocket ss = null;
// ... more code
}
And the activation method should use the reference:
private void activateInstance() throws Exception {
try {
final int LOCK_PORT= 54321;
ss = new ServerSocket(LOCK_PORT); // note the missing "ServerSocket" before ss
} catch (Exception e) {
System.out.println(e);
throw e;
}
}
The problem is that if you create the variable ServerSocket inside a method, the garbage collector will clean it once the method is done. If the variable is declared above, the garbage collector wont collect and clean it because the declared variable will stay instantiated but with NO reference.
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 ...
Is it correct to create a thread and call its start() method inside a class' constructor as done here?
public class Server implements Runnable {
private ServerSocket server;
public Server(int port) {
try {
//Opens a new server
server = new ServerSocket(port);
} catch (IOException ioe) {
ioe.printStackTrace();
}
new Thread(this, "Server").start();
}
#Override
public void run() {
}
}
IMHO, do not do this. You're allowing the this reference to escape during construction.
Granted, your code isnt doing it but what if your code looked like this:
public Server(int port)
{
new Thread(this, "Server").start();
try
{
//Opens a new server
server = new ServerSocket(port);
}
catch (IOException ioe){ ioe.printStackTrace(); }
}
#Override
public void run(){
if(server == null)throw new NullPointerException();// this may happen
}
}
The server reference may be null even though no exception occurs. This is because the Thread will use the created runnable and invoke the run method even if the constructor of your class hasn't finished.
Server s = new Server();
Thread t = new Thread(s, "Server").start();
is more testable. It allows you to create an instance of Server and unit test its methods without spawning a thread.
A couple more good reasons to split the Thread.start() from the constructor:
If you ever want to use some other framework/system to run the threads, such as a java.util.concurrent.Executor, you may do so.
If you ever want to interrupt the thread, you need a reference to it. Creating the Thread in a separate line of code makes this somewhat more routine / idiomatic. e.g.
Thread rememberMe = new Thread(server).start();
In your original code, Server could have a field to remember myThread, but it didn't.
public class Server implements Runnable
{
private ServerSocket server;
/**
* Because the constructor is private, the only way to instantiate a Server is through
* the static factory method.
* If there are any instantiation problems, the static factory method will fail in
* first line, before it is put into a thread.
* It will be put into a thread before being released.
**/
public static Server startServer ( int port )
{
Server server = new Server ( port ) ;
new Thread ( server , "Server" ) . start ( ) ;
return server ;
}
private Server(int port)
{
try
{
//Opens a new server
server = new ServerSocket(port);
}
catch (IOException ioe){ ioe.printStackTrace(); }
// don't release me into the wild yet!
// new Thread(this, "Server").start();
}
#Override
public void run(){
}
}