I have created a simple database application using rmi. It works fine with my local wireless network. But now i want to connect my client to the server through the internet. I know that, this can be achieved with setting up port forwarding in the router. But i want it to work in any computer which is connected to the internet using wifi connections, dialup
connections etc. How to do that?
what to write here? Naming.lookup ("rmi://?????????????");
As I am quite new to java, Please give me a detailed answer with a simple code example.
Thanks in advance
I hope you are messed up with Java RMI Concept. Irony is that a few days ago I was also thinking up the same except that I was thinking to connect up on my internal network.
There are two kinds of classes that can be used in Java RMI.
A Remote class is one whose instances can be used remotely. An object
of such a class can be referenced in two different ways:
1. Within the address space where the object was constructed, the object is an ordinary object which can be used like any other object.
2. Within other address spaces, the object can be referenced using an object handle. While there are limitations on how one can use an
object handle compared to an object, for the most part one can use
object handles in the same way as an ordinary object.
A Serializable class is one whose instances can be copied from one
address space to another. An instance of a Serializable class will be
called a serializable object. In other words, a serializable object is
one that can be marshaled.
SO, HERE COMES THE ANSWER TO YOUR QUESTION,ASSUMING YOU ARE TALKING ABOUT REMOTE CLASS ON DIFFERENT SYSTEM(SERVER).
The name of a remote object includes the following information:
The Internet name (or address) of the machine that is running the
Object Registry with which the remote object is being registered. If
the Object Registry is running on the same machine as the one that is
making the request, then the name of the machine can be omitted.
The port to which the Object Registry is listening. If the Object
Registry is listening to the default port, 1099, then this does not
have to be included in the name.
The local name of the remote object within the Object Registry.
The URL for a remote object is specified using the usual host, port and name:
rmi://host:port/name
host = host name of registry (defaults to current host)
port = port number of registry (defaults to the registry port number)
name = name for remote object
Assuming that your code is lying on the server having host-name as "XYZ.edu/home/CLasses"(you can give the DNS/IP-Address of server and include the location of the Class file),port-number="1099"(default) and name of the remote Object="abc" for your ABC.java Class in Server. In this way one will be able to call the Remote Object from different machines. Also, you need to keep the whole Server code on the Internet Address so that Clients can access them from the Internet(one can't access the offline-code present in your machine). Then only it can happen!!!
Here is the example Client program:
/**
* Client program for the "Hello, world!" example.
* #param argv The command line arguments which are ignored.
*/
public static void main (String[] argv) {
try {
HelloInterface hello =
(HelloInterface) Naming.lookup ("//ortles.ccs.neu.edu/Hello"); //see here the address of the server hosting the Server file,you can omit port number,it'll take default port 1099.
System.out.println (hello.say());
} catch (Exception e) {
System.out.println ("HelloClient exception: " + e);
}
}
Related
I have a server which allows RMI connections. It exposes a "Server" object on the registry for remote calls, which has a method "authenticate". That method, if successful, returns a "user" object. This user object can then be used by the client to get some data.
It looks like this:
RMIServer server = new RMIServer ();
Naming.rebind("rmi://"+ hostName +"/" + AUTH_OBJECT_BINDING, server);
RMIServer then has a method:
public InterfaceUser Authenticate(String username, String password);
This method checks the username/pw and returns a user object (actually the interface). The user object saves some string which contains the username, and a list of permissions. This can then be checked when calling other methods further down the line.
My question is this:
Someone wants to develop a (another) client for the server, to do this I would give them the interfaces required to interact with it (e.g, the InterfaceUser interface, as well as others). I would need to set up a fake "development" server somewhere to allow them to do this, which they can connect to. Is it possible for that developer to use the interfaces to allow it to get an instance of "InterfaceUser" from the real server without correctly authenticating? For example, Bob logs in to the real server, the server creates a User object which implements InteraceUser. Can Alice, with the interfaces, hijack that object or find it somehow on the registry? All other objects are exported on the same port (if this makes a difference).
Or, can Alice authenticate with the fake server, then somehow use that to access the real server? Let's assume that all usernames/passwords are different on the "real server" and the "development server"
Thanks, any help is appreciated.
Alice can't get any user object unless she can login to a server that provides it.
Any user object Alice does get is bound to the server that created it, and can't be used on another server. It doesn't even survive power cycling of the correct server.
Does that answer your question?
I have an rmi server on a box with two public interfaces. When a client connects, it always returns the wrong ip address in the UnicastServerRef2 [liveRef: [endpoint:[192.x.x.x:xxxx .... The connection from the client goes to the other interface with ip 10.x.x.x. Does anybody know how to solve this? I do not want to specify the ip when binding the stub. It works then, but I would like it to listen on all interfaces (0.0.0.0).
If I specify java.rmi.server.hostname=myhostname and use a RMIServerSocketFactory to create a ServerSocket[addr=myhostname/10.x.x.x,localport=xxxx], it still returns the 192.x.x.x adress to the client as remote endpoint. Weird enough I have two UnicastRemoteObjects objects on diffrerent ports and one of them returns the right address, the other not.
Any Ideas how to make it to return the endpoint with the ip of the interface the connection was made to?
That's what the java.rmi.server.hostname property is for. Set it at the exporting JVM to whatever IP address you want the clients to use to connect to it.
If I have 2 public IPs on a linux system they get represented as virtual network interface names. This is what Linode says about it.
Linodes have one network interface, eth0. When you add IP addresses,
you create virtual network interfaces named eth0:1, eth0:2... eth0:n.
I need to use 2 different Java apps on the same Linode and I want each of them to use a different public IP. I would need to specify which network interface each Java instance uses. Would this be possible? I'm using Debian Linux.
You can use the ServerSocket(int port, int backlog, InetAddress address) constructor to create a server socket bound to a particular IP address (3rd parameter). The address determines the network interface that will be used.
For example:
String ip = "192.168.1.54"; // read from config file
int port = 9090; // likewise
InetAddress addr = InetAddress.getByName(ip);
ServerSocket serverSocket = new ServerSocket(port, -1, addr);
If you have two different apps and two different IP addresses you'll likely want one app to always use one IP, and the other app to always use the other one. To make sure this association doesn't change you should store the IP address each app is supposed to use in a configuration file or something similar.
On a server of our private network we have an HttpServlet which is contacted by a PC of the same network.
We need to know the hostname of the client which contacts the server. To do this we call the
getRemoteHost method of the HttpServletRequest.
Some times this method returns the PC name of the client (wanted behavior) and some other the method returns the IP address. (same client, same server, same private network)
The API says:
java.lang.String getRemoteHost()
Returns the fully qualified name of the client or the last proxy that sent the request. If the engine cannot or chooses not to resolve the hostname (to improve performance), this method returns the dotted-string form of the IP address. For HTTP servlets, same as the value of the CGI variable REMOTE_HOST
Returns:
a String containing the fully qualified name of the client
I see that for HTTP servlet that value is the same of the CGI variable REMOTE_HOST. What does it mean? Is it up to the server to decide to resolve the address or not? Is there a way to force this behavior?
In Tomcat, for example, the connector has a setting "enableLookups" which is disabled by default for performance reasons. See http://tomcat.apache.org/tomcat-7.0-doc/config/http.html
Other containers may have different methods of doing the same thing.
First off, I'd love to post some real code for this question, but I can't because it's far too many lines. That said, here's my situation:
Server Side
I have an RMI Server that waits for Clients to connect and "register" themselves, so that the Server can make function calls on Clients. Basically, the server has a published function that works like the following pseudo-code:
public class Server extends UnicastRemoteObject implements ServerInterface{
public Server(){ /* Server publishes itself here */ }
...
/** One of many methods visible to a remote Client */
public void registerClient(Client c) throws RemoteException{
//1. Make some remote calls on 'c' for book-keeping purposes
//2. Store reference to c to make calls on it later
}
}
Client Side
On Startup, the Client makes a call to Naming.lookup([url]) to get a stub to the Server that I'll call serverRef, then calls serverRef.registerClient(this). The problem happens the first line of the server's registerClient(Client c) method.
Problem
When the server makes its first remote method call to the Client inside the registerClient method, a RemoteException is thrown. While client and server machines are on the same subnet, the client's machine has a secondary IP address. So the IPs look something like this:
Server Machine IPs: 123.45.67.1
Client Machine IPs: 123.45.67.2, 192.168.67.2
The RemoteException that gets thrown during the Server's first remote call back to the client indicates that the Server is trying to connect to the Client's 192.168.67.2 address, which is what's causing the failure. The Server should be trying to connect to the 123.45.67.1 address. I know that disabling the network interface that belongs to the second IP address would fix the problem, but this isn't really an option for me.
Is there any way to "tell" server-side RMI which IP address to connect on when opening a connection to a new client-side object stub?
There are several possible solutions, including
write a custom client socket factory
specify addresses in java.rmi.server.hostname property
-Djava.rmi.server.hostname=ip_address
etc
Check out this link:
http://weblogs.java.net/blog/emcmanus/archive/2006/12/multihomed_comp.html
These links are also useful:
java rmi -Djava.rmi.server.hostname=localhost still opens a socket listening on 0.0.0.0
http://www.chipkillmar.net/2011/06/22/multihomed-hosts-and-java-rmi/4/java-rmi-djava-rmi-server-hostname-localhost-still-opens-a-socket-listening-on
*