We currently have a server that is creating a new thread for each request he gets, so basically the server gets data that he needs to save later.
Now we got the request to implement RMI where we can observe what kind of data is currently being saved.
How can I handle this the best way? Shall I make an RMI Server for each thread? Can I have multiple instances of the same service on the same address and let my observer register to all of them?
I'm using the google example for the RMI access:
https://sites.google.com/site/jamespandavan/Home/java/sample-remote-observer-based-on-rmi#TOC-Running-the-server-client
You don't need a remote object per thread, because you won't even have visible threads. A remote object is already multi-threaded and already takes care of its own incoming connections. You will be throwing stuff away rather than adding.
You might need a remote object per client, if you wamt them to behave like sessions, but that's a different story.
Related
I want to have multiple clients communicating via a server AND for the clients to be able to affect each other via what information they pass to the server (like a chat maybe).
Background:
I am working on an assignment in regards to socket programming in Java, with a server and multiple clients, and since it is an assignment I will refer to public documentation to describe my problem. The assignment is to write a game and it has been going quite well. To set up the sockets I have been following the format from this tutorial:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
In the documentation above we have one server that keeps calling a serverThread object, using the accept() method to establish contact with a client that connects. The server is just listening and creating threads for the clients to hop in, we also have an object that is a protocol of communication but I don't mind that for now. All in all the documentation provides the following classes:
KKMultiServer (https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServer.java)
KnockKnockClient (https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KnockKnockClient.java)
KKMultiThread (https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServerThread.java)
(KKProtocol)
Problem:
I have managed to write a game that works very well, but here is my problem, every client is in isolation within their own thread. I want multiple clients to be able to interact with each other via the server, if player 1 moves it should update the screen for player 2, and vice versa is my intention. Right now, if multiple clients connect to the serverThread it is as if they are in two separate games, which is not what I want.
In the java documentation above we can have the same problem, with KnockKnock jokes. I want one client to be able to write something, and then for the server to pass on to another client what the first client wrote. However, how can we have data from one client that can be passed to another client via the server, if they are all isolated in different threads (as per the documentation)?
I have an instance to a class A that implements java.rmi.Remote.
In order to check the health of the connection to the RMI Server, I invoke a custom-made, trivial member function of the instance of A and see if an Exception is thrown. That's not really elegant. Therefore my question:
Is there any native way to check if the connection is available for method invocation on the instance of A, i.e. without the need to actually try to call a member function?
A special case is: Should the RMI server be restarted during the lifetime of the instance of A on the client side, then the instance of A becomes invalid and defunct (although the server might be back up and healthy).
From Java RMI FAQ :
F.1 At what point is there a "live" connection between the client and
the server and how are connections managed?
When a client does a "lookup" operation, a connection is made to the
rmiregistry on the specified host. In general, a new connection may or
may not be created for a remote call. Connections are cached by the
Java RMI transport for future use, so if a connection is free to the
right destination for a remote call, then it is used. A client cannot
explicitly close a connection to a server, since connections are
managed at the Java RMI transport level. Connections will time out if
they are unused for a period of time.
Your questions :
Is there any native way to check if the connection is available for
method invocation on the instance of A, i.e. without the need to
actually try to call a member function?
This question boils down to how to check programmatically that a given server/system is UP. This question has already been answered several times here and several other forums. One such question which answers this is Checking if server is online from Java code.
A special case is: Should the RMI server be restarted during the
lifetime of the instance of A on the client side, then the instance of
A becomes invalid and defunct (although the server might be back up
and healthy).
Then again, the answer is pretty easy. If the instance of the class was busy performing a step within the remote method invocation, then there would be a connection related exception thrown instantly.
Again, from RMI FAQ, D.8 Why can't I get an immediate notification when a client crashes? :
If a TCP connection is held open between the client and the server
throughout their interaction, then the server can detect the client
reboot(I'm adding here: and vice-versa) when a later attempt to write to the connection
fails (including the hourly TCP keepalive packet, if enabled).
However, Java RMI is designed not to require such permanent
connections forever between client and server(or peers), as it impairs
scalability and doesn't help very much.
Given that it is absolutely impossible to instantly determine when a
network peer crashes or becomes otherwise unavailable, you must decide
how your application should behave when a peer stops responding.
The lookup would keep on working perfectly, till the server is UP and doesn't get down while the client is performing operation on the remote method. You must decide here how your application should behave if the peer restarts. Additionally, there is no such concept as session in RMI.
I hope this answers all of your questions.
Your question is founded on a fallacy.
Knowing the status in advance doesn't help you in the slightest. The status test is followed by a timing window which is followed by your use of the server. During the timing window, the status can change. The server could be up when you test and down when you use. Or it could be down when you test and up when you use.
The correct way to determine whether any resource is available is to try to use it. This applies to input files, RMI servers, Web systems, ...
Should the RMI server be restarted during the lifetime of the instance of A on the client side, then the instance of A becomes invalid and defunct (although the server might be back up and healthy).
In this case you will get either a java.rmi.ConnectException or a java.rmi.NoSuchObjectException depending on whether the remote object restarted on a different port or the same port.
When i try to run 2 wget commands simultaneously to my server (http://myserver), looks like tomcat allocates two threads to process them. But i believe when tomcat receives two simultaneously from same ip address, it will not create a new thread for processing the second request as it considers both the requests come from same session.
If i want to check if both the threads are same or different, is using thread.getId() the only way? I think this id may be reused for new threads. Is there any unique property of the thread existing to check its identity other than threadid?
I suggest to never rely on threads to identify their source. There are no Servlet spec guarantees about threads, and newer Servlet spec implementations make use of NIO. You are skating on a thin ice.
Web servers will almost always assign multiple threads (or processes) to multiple simultaneous requests, since the client can work faster when it does not have to wait for each response.
Newer servers may use asynchronous IO (nio), however, and a single thread can simultaneously serve many clients.
Yes, Thread.getId() is a way of identifying threads.
Session IDs are the mechanism used to identify requests from a single client.
The IP address is not a good way to do that, since multiple machines can expose the same IP when hiding behind a NAT.
I believe Tomcat will always create a new thread of execution irrespective of whether it comes from the same IP or not. In case, the client application running on the particular IP has a mechanism to send across the session-id, then Tomcat will simply associate the same session context with the request thread [making it stateful].
in your case, you'll need to customise wget to hold on to the session-id [the Tomcat web-app might send it across through a cookie or as a url parameter - jsessionid]. wget will then need to send it back with the subsequent requests [url rewrite and include the jsessionid parameter, or exchange cookies]. this way Tomcat will be able to treat each request coming from a unique client instance and associate a state with it.
What do I need to worry about when doing callbacks in RMI? I just need a simple client notification mechanism to avoid excessive polling.
I found an online example and it looks pretty straightforward, the client just implements an interface that extends Remote (like the server does) and passes it to the server, which can then call back its methods. I'm guessing the remote callback can occur on any thread, so I have to assume it will be asynchronous to my client application's normal threads. What else is there?
Two things.
RMI callbacks almost certainly won't work through firewalls
RMI callbacks execute on a different thread from the original client call to the server. You can get unexpected synchronization deadlocks if you don't take that into account.
i have two clients in two different processes that communicate through RMI with the server.
my question is:
what happends if both clients invoking the server's stub at the same time?
thanks for you time,
me
This tutorial demonstrates the threaded nature of RMI servers (see task 7.1). They quote from the RMI spec:
A method dispatched by the RMI runtime
to a remote object implementation (a
server) may or may not execute in a
separate thread. Calls originating
from different clients Virtual
Machines will execute in different
threads. From the same client machine
it is not guaranteed that each method
will run in a separate thread
so invocations from different clients will result in execution via different threads in the server.
Nothing untoward by default - it's exactly the same as invoking a method on any other object from two threads simultaneously. The 1 server to many clients model is what network protocols like RMI are for.
Access to any shared data within the server needs to be regulated by synchronized blocks if need be. It depends what the server is doing.