I do not quite understand what
UnicastRemoteObject.exportObject(this, 0);
is for. Is it to register an object on rmi server or what. Hope someone can shine me some light.
From Getting Started Using Java RMI
The static method UnicastRemoteObject.exportObject exports the supplied remote object to receive incoming remote method invocations on an anonymous TCP port and returns the stub for the remote object to pass to clients. As a result of the exportObject call, the runtime may begin to listen on a new server socket or may use a shared server socket to accept incoming remote calls for the remote object.
Port 0 means it'll pick a random available port for RMI service port. This might be an issue if you're working in a firewalled/NATted environment which requires you to open a port between Client and RMI server hence instead you can specify something other than 0.
Related
I have a client server structure. The server exposes a service with RMI, let's say it is: RemoteInterfaceA. The service is regualary exported using UnicastRemoteObject.exportObject(service, port) and bound in the RMI Registry.
The server however must update something in the client so also the client creates a RemoteInterfaceB, it exports it using UnicastRemoteObject.exportObject(update, port). It cannot however create a Registry (because unlike the server it is not reachable from the internet). To give to the server its update stub, I pass the update as an argument of a service (RemoteInterfaceA) method.
Will it work?
It will work, firewalls permitting. As you say the client isn't reachable from the Internet, it won't for you. The server will get a NetworkUnreachableException or a connect timeout when it tries to callback the client.
I've recently started to learn about socket usage, more specifically in Java.
In this link is shown a simple client-server UDP application.
My question is: How does the client receives the response with receive() method when this datagramsocket object calling receive doesn't have a port set?
The client initializes its DatagramSocket via the nullary constructor, which binds the socket to some available port (chosen in an unspecified manner) on the wildcard address. That's quite different from not having a port set -- there is a port set, but it is chosen by the computer, not explicitly specified by the program.
When the server receives a message, it extracts not only the message data, but also the source address and port. It sends its response to that address and port. The client successfully receives it via the same socket with which it sent the original message, because it's still bound to the same port, even if you don't know exactly which one that is.
the first time you send a packet using that socket, an ephemeral port will be allocated. If you need a specific port then you can bind it explicitly which is needed for bootp for instance. But in the most simple case bind is not needed and you get the ephemeral port.
The peer will see this port in the UDP header because in there is both the source and destination port.
As a side note this mechanism is the same for TCP clients. When they do a call to connect() unless the socket was bind to a specific port, an ephemeral port will be allocated by the clients kernel and that one will be used for the lifetime of the connection.
The ephemeral ports are usually in a specific range, there is kindof a pool of ports for UDP and TCP. The kernel usually has a mechanism to take from the pool starting from the beginning and gradually incrementing till the end is reached upon which he'll start from the beginning. Skipping ports that are still in use of course. It is called the ephemeral port range, and it is specific to the os.
how to change/view ephemeral port range in windows machines
The guest's computer can be on a network other than the server's.
If it isn't, everything is OK, but when he is, a ConnectException is thrown.
Do you know why ?
Extra info:
I modified the port from 1099 (default) to 80 to try to solve the problem, doesn't work.
Using Wireshark, I saw that guest were using port 50740. I don't understand why, and never saw this number before.
I grant all permissions with a .policy file.
Edit :
I already have server IP defined by a .bat. I also have Locate.createRegistry(80); at the beginning of my client. Is it enough to make client use port 80 ?
Strange thing is that i can try to log in (my app asks for a login when launched), see if my credentials are OK or not. Then, if client isn't on the same network, the ConnectException is thrown.
I modified the port from 1099 (default) to 80 to try to solve the problem, doesn't work. Using Wireshark, I saw that guest were using port 50740. I don't understand why, and never saw this number before.
When an RMI client wants to talk to a remote object it typically starts by contacting the RMI registry on port 1099 to ask where it can find the target object. The registry replies with a stub containing the address of the target object (host name and port number), and the client can then connect to the target host and port to talk to the remote object.
If you don't specify an explicit port number in the call to the UnicastRemoteObject superclass constructor or the static exportObject method, then RMI will select a random available port number to use. That's probably where the 50740 comes from - it's the port that the target object is listening on, as opposed to the registry.
But the second element of the target object address is the host name - if the object is listed in the registry at an address like 127.0.0.1:50740 then a client on a different machine will end up trying to connect to the object in the wrong place (on the client's localhost rather than the server's). The solution is to ensure that the objects are bound in the registry under a proper host name or IP address that is resolvable from the client - in theory this should happen automatically, but sometimes RMI gets it wrong. The solution is to pass a system property to the RMI server (the process that is binding the target object in the registry)
java -classpath .... -Djava.rmi.server.hostname=192.168.0.1 com.example.MyRmiServer
Replace 192.168.0.1 with the correct IP address that the client machine will use to talk to the server.
You need to export your remote objects on a fixed port number, and open that port in your firewall. The easiest port to use is 1099 as it's already reserved, but it requires that you start the Registry in your JVM via LocateRegistry.createRegistry() instead of using rmiregistry, so you can share the port.
As far as I know, RMI uses random ports for communicating between object's stub and remote object. To make things work through firewall, we need to know which ports to open.
Now, isn't it enough to create a stub using UnicastRemoteObject.exportObject(Remote obj, int port)?
According to documentation, it "Exports the remote object to make it available to receive incoming calls, using the particular supplied port."
Does it create a stub that, for any subsequent invocation of remote method, uses this particular port for communication with remote object? If not, then what this port argument does?
Does it create a stub that, for any subsequent invocation of remote method, uses this particular port for communication with remote object?
Yes.
If not, then what this port argument does?
It does that. It also determines what port the remote object is listening on, of course.
I am asked to build a server client chat application with dynamic ports Allocation ,my problem is that i can't retrieve the dynamic port from the client class , i tried several methods :Static members ,Singleton Design Patterns..but without success .Is there a method to do this ?
This is my server Constructor :
public Serveur() throws IOException{
listen=new ServerSocket(0);
port=listen.getLocalPort();
System.out.println("Le serveur est demarre");
}
when i acces the variable port from the client class ,it returns the next free port ,which is incorrect ,please Help!!
When I access the variable port from the client
Eh? You can't access the variable port from the client. You don't know what it is.
You have to work out a way for the server to tell the client what the port number is. You'll have to broadcast or multicast it from the server, or have the clients broadcast or multicast requests for it.
Or use a fixed port. It's much easier.