RMI - work in the same machine, not in LAN - java

I am trying to establish two-communication between one server and two clients. This works very well when all programs run on the same machine but it doesn't work when I try using LAN network.
I got the error :
java.rmi.ConnectException: Connection refused to host: 192.168.1.24; nested exception is:
java.net.ConnectException: Connection timed out: connect
Here is the server code :
public class Server{
private Game partie; // The class Game extends UnicastRemoteObject and implements ServerInterface
public Server() throws RemoteException {
System.setProperty("java.rmi.server.hostname", "192.168.1.24");
partie = new Game();
LocateRegistry.createRegistry(1099);
try{
Naming.rebind("Server", partie);
}
catch(Exception e){
e.printStackTrace();
}
}
public static void main(String argv[]) throws RemoteException{
new Server();
}
}
Here is the constructor of the client code :
public Client(String aName, String aServerAdress) throws RemoteException {
super();
name = aName;
ServerAdress = aServerAdress; // = "192.168.1.24"
theRegistry = LocateRegistry.getRegistry(ServerAdress);
try {
serverInterface = (ServerInterface) theRegistry.lookup("Server");
} catch (NotBoundException e1) {
e1.printStackTrace();
}
try {
theRegistry.bind(name, this); // For two-way communication
} catch (AlreadyBoundException e) {
e.printStackTrace();
}
serverInterface.registerClient(name);
}
Where registerClient(String name) code is approximately (in Game class) :
cd_client = (ClientInterface) Naming.lookup("rmi://127.0.0.1/" + name);
All firewalls are disabled.
I have been working on this problems for many hours and I have still not found what is wrong. I would really appreciate if you could help me a bit.
Thank you

Change all occurances of 127.0.0.1 (except registry binding) to your LAN IP address (192.168.1.24 in your case)
127.0.0.1 is a Loopback address:
"Loopback (loop-back) describes ways of routing electronic signals,
digital data streams, or flows of items from their originating
facility back to the receiving end of the source without intentional
processing or modification. This is primarily a means of testing the
transmission or transportation infrastructure."
-- from Wikipedia

Related

Client Server communication in Java: how to distinguish between sockets

I'm now processing a client-server communication in Java, by using Socket and ServerSocket objects.
Once the server has been initialised, it puts on hold with new clients through the accept() method, from ServerSocket class; I immediately provide to put this socket in a client map on the server:
- keys: ClientNode(Socket s, CommunicationChannels channels);
- values: Info();
(CommunicationChannels contains ObjectOutputStream and ObjectInputStream from socket; Info contains some information about client, as username, messages etc..).
Given that, at the very beginning, the socket does not have any other information on the client besides the socket itself, first insertion on the map is map.put(ClientNode, null). I will fill the field "value" afterwards.
Now, on Client class, I am going to initialise a Socket("127.0.0.1", 13001), namely with a loopback address and gate 13001. Once communication channels have been initialised, client connects to the server.
Once the client starts, he takes a remote copy of the server through RMI (stub) libraries and the server makes a register() method available: it would allow to use this method to write requested information (from the clients) on the map.
How can the client go back to the socket with which it has been registered on the server? Frankly speaking, I supposed that accept() method from ServerSocket could take the socket established on the startup client back to the server, namely with the new Socket("127.0.0.1", 13001), but it seems to me that this does not happen.
Here you can find parts of the code, so you can better understand what I'm talking about. I've already taken into account a few things that I will share with you in case of need.
public class Server implements Runnable, RemoteServices {
...
private Map<ClientNode, Info> map = new HashMap<ClientNode, Info>();
...
public void run() {
ServerSocket ss = null;
try {
ss = new ServerSocket();
while (true) {
if (!ss.isBound()) {
ss.bind(new InetSocketAddress(ipServer, port));
}
Socket client = ss.accept();
CommunicationChannels channels = new CommunicationChannels(new ObjectOutputStream(client.getOutputStream()), new ObjectInputStream(client.getInputStream()));
map.put(new ClientNode(client, channels), null);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// RemoteServices implementa Remote e mette a disposizione register()
public void register(Info info) throws RemoteException {
// TODO
}
public class Client implements Runnable {
...
...
#Override
public void run() {
Socket client = null;
try {
client = new Socket(ipServer, port);
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
Registry registry = LocateRegistry.getRegistry("127.0.0.1");
stub = (RemoteServices) registry.lookup("remoteObject");
Info info = new Info();
info.setID(getID());
info.setUsername("Giordano");
stub.register(info);
} catch (IOException e) {
System.err.println("Spiacente: il server ha terminato l'esecuzione.");
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}
Remarks:
I have not included the code of some classes because I thought it was superfluous; for example the "info" class is just a series of "getter and setter" of some fields; the CommunicationChannels class represents communication channels of the client, taken directly from the socket, etc ..
The server, after the accept(), does not instantiate any thread to communicate with the client because communication has to come afterwards. However, if there was a way to solve my problem with a thread of communication I would find a way to fix it.
My question starts from the need to make interact 2 clients with a server without using more PCs; therefore all clients will have the IP loopback and therefore I cannot use the IP address as a discriminating between two sockets, otherwise I would have already solved it.
In other words, I know that methods as socket.getInetAddress().getHostAddress() can help me to distinguish between two socket, but if I initialise two clients on the same PC I have to use loopback address and the method always returns "127.0.0.1".
The register() method is obviously incomplete even in the signature; once understood how to compare the server socket and client one through a Serializable discriminating object (like the hashcode()) probably I might put it in the arguments of the method, so you can easily make the comparison.
Finally, main() methods:
public static void main(String[] args) {
Server server = new Server("127.0.0.1", 13001);
RemoteServices stub;
try {
stub = (RemoteServices) UnicastRemoteObject.exportObject(server, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("remoteObject", stub);
(new Thread(server)).start();
} catch (RemoteException e) {
System.err.println("Verificare l'apertura dei registri");
} catch (AlreadyBoundException e) {
System.err.println("Server già attivo. Controllare che i registri siano chiusi correttamente.");
}
}
public static void main(String[] args) { Client client = new Client("127.0.0.1", 13001);
new Thread(client).start();
}
I really hope everything is clear and that you can help me.

Pyro4 connect with java

Hi all I have question related with Pyro4 and Java. My question is how can I send information between RMI server in Java and clients RMI in Python?.
This is my code, I don't have any errors but I can't send anything.
Java Code:
implements ReceiveMessageInterface
{
int thisPort;
String thisAddress;
Registry registry; // rmi registry for lookup the remote objects.
// This method is called from the remote client by the RMI.
// This is the implementation of the �gReceiveMessageInterface�h.
public void receiveMessage(String x) throws RemoteException
{
System.out.println(x);
}
public RmiServer() throws RemoteException
{
try{
// get the address of this host.
thisAddress= (InetAddress.getLocalHost()).toString();
}
catch(Exception e){
throw new RemoteException("can't get inet address.");
}
thisPort=3232; // this port(registry�fs port)
System.out.println("this address="+thisAddress+",port="+thisPort);
try{
// create the registry and bind the name and object.
registry = LocateRegistry.createRegistry( thisPort );
registry.rebind("rmiServer", this);
}
catch(RemoteException e){
throw e;
}
}
static public void main(String args[])
{
try{
RmiServer s=new RmiServer();
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
And this is my code in Python:
import Pyro4
proxy=Pyro4.core.Proxy("PYRONAME:PhDJara/127.0.1.1")
print("5*11=%d" % proxy.multiply(5,11)) print("'x'*10=%s" %
proxy.multiply('x',10))
Thanks for your help.
jarain78
What makes you think that you should be able to connect these two?
Pyro4 is only conceptually similar to Java's RMI, but they're two totally different protocols. You cannot connect them directly.
If you want to write a Python client using Pyro and talk to a server, that server has to be a Pyro server. The only way to create one in Java is by using Jython + Pyro.

Client-Server communication between Raspberry Pi and Android

I am trying to setup a client-server system with the Pi acting as the server, and the Android device being the client. Every time I run the code (I cobbled together from the internet) the client throws an IOException:
Connection timed out: connect
I just discovered that when I try to ping the Pi's IP it is unreachable.
How can I fix this?
Note I am currently testing Java code on a Windows PC until I get it working.
Client Code (Java):
import java.io.*;
import java.net.*;
public class client
{
static Socket clientSocket;
static String homeIp="192.168.0.105"; //internal ip of server (aka Pi in this case)
static int port=4242;
public static void main(String [] args)
{
sendToPi("I sent a message");
}
public static void sendToPi(String s)
{
//wordsList.append("in sendToPi()\n");
System.out.println("in sendToPi()");
//Log.e("aaa","in sendToPi()\n");
try {
clientSocket = new Socket(homeIp, port);
PrintStream out = new PrintStream(clientSocket.getOutputStream());
out.println(s);
} catch (UnknownHostException e) {
//Log.e("aaa","Don't know about host: "+homeIp+"."+e.getMessage());
System.out.println("Don't know about host: "+homeIp+"."+e.getMessage());
//System.exit(1);
} catch (IOException e) {
//Log.e("aaa","Couldn't get I/O for the connection to: "+homeIp+"."+e.getMessage());
System.out.println("Couldn't get I/O for the connection to: "+homeIp+"."+e.getMessage());
//System.exit(1);
}
}
}
Server Code (C): I used code from here exactly as written. compiled as server. Started with ./server 4242
In my case the solution was to explicitly forward the client port in my router.

Java RMI Client access denied

I have a small Java RMI Server and Client program I'm writing. I have spent some time trying to figure out the error messages without success.
The Client generates the following error:
Trying to connect to: 127.0.0.1:3232
ERROR!!!: StockClient: main: Could not connect to the server: java.rmi.UnmarshalException: Error unmarshaling return header; nested
exception is:
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.io.EOFException
java.io.EOFException
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:209)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at StockClient.StockClient.main(StockClient.java:44)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:250)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:195)
... 3 more
With the server the following error only when the client attempts to connect.
this address=localhost/127.0.0.1,port=3232
Exception in thread "RMI TCP Connection(idle)" java.security.AccessControlException: access denied
(java.net.SocketPermission 127.0.0.1:62586 accept,resolve)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:549)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkAccept(SecurityManager.java:1157)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.checkAcceptPermission(TCPTransport.java:636)
at sun.rmi.transport.tcp.TCPTransport.checkAcceptPermission(TCPTransport.java:275)
at sun.rmi.transport.Transport$1.run(Transport.java:158)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Because of the server error I'm fairly sure its a security or registry error, security policy for the server is:
grant {
permission java.security.AllPermission;
};
and being run with the following argument
-Djava.security.policy=client.policy
I've tried everything I can find but seem to keep going around in circles.
relevant methods:
Server:
public static void main(String[] args)
{//main(...) starts
// set up the data structures and data
//add users
//Users hard coded as this is an example proof on concept program
//Names and passwords not hashed for simplicity
User alpha = new User("Alpha", "AlphaPass");
User omega = new User("Omega", "OmegaPass");
users.add(alpha);
users.add(omega);
//startup the RMI server
try
{
System.setSecurityManager(new RMISecurityManager());
StockServer server = new StockServer();
StockServerInterface inter = (StockServerInterface)
UnicastRemoteObject.exportObject (server,0);
// create the registry and bind the name and object.
registry = LocateRegistry.createRegistry(thisPort);
registry.rebind("StockServer", inter);
}
catch (Exception e)
{
System.out.println("Unable to create StockServer: " + e);
e.printStackTrace();
System.exit(1);
}
}//main(...) ends
/**
* Constructor for StockServer
*
* #throws RemoteException
*/
public StockServer() throws RemoteException
{
//try to get the host machine's IP address
try
{
// get the address of this host.
thisAddress = (InetAddress.getLocalHost()).toString();
} catch (Exception e)
{
throw new RemoteException("can't get inet address. " + e);
}
//Set the port
thisPort = 3232;
//Print out the server address and port
System.out.println("this address=" + thisAddress + ",port=" + thisPort);
}
Client:
private static StockServerInterface stockServer;
static public void main(String args[])
{
Registry registry;
//get the server address from the args
String serverAddress = args[0];
//get the server port from the args
String serverPort = args[1];
//Let the user know we are about to try to connect
System.out.println("Trying to connect to: " + serverAddress + ":" + serverPort);
try
{
// get the registry
registry = LocateRegistry.getRegistry(
serverAddress,
(new Integer(serverPort)).intValue());
// look up the remote object
stockServer = (StockServerInterface) (registry.lookup("StockServer"));
//Authenticate the user
authenticate();
//setup the hashset
HashSet<Stock> hashStockSet = null;
//setup the hashset of desired stocks
try
{
hashStockSet = getHashSet();
} catch (IOException e)
{
e.printStackTrace();
System.exit(1);
} catch (ClassNotFoundException e)
{
e.printStackTrace();
System.exit(1);
}
//bit of a heavy handed infinte loop so we continue to get the loop
while(true)
{
//Run the ticker
ticker(hashStockSet);
}
// call the remote method
}
catch (RemoteException e)
{
System.out.println("ERROR!!!: StockClient: main: Could not connect to the server: "+e);
e.printStackTrace();
}
catch (NotBoundException e)
{
System.out.println("ERROR!!!: StockClient: main: Could not connect to the server: "+e);
e.printStackTrace();
}
You don't need a SecurityManager in an RMI server unless the client is relying on the codebase feature to supply the server with classes. Either remove it, or debug the .policy file. Clearly the one you've written isn't being loaded.
Run your server with -Djava.security.debug=access,failure and you will see where all the security domains are getting their configurations from, and the domain that is failing at the point where the exception is thrown.

Java Networking "Connection Refused: Connect"

I have been trying to get a simple networking test program to run with no results.
Server:
import java.io.*;
import java.net.*;
public class ServerTest {
public static void main(String[] args) {
final int PORT_NUMBER = 44827;
while(true) {
try {
//Listen on port
ServerSocket serverSock = new ServerSocket(PORT_NUMBER);
System.out.println("Listening...");
//Get connection
Socket clientSock = serverSock.accept();
System.out.println("Connected client");
//Get input
BufferedReader br = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
System.out.println(br.readLine());
br.close();
serverSock.close();
clientSock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Client:
import java.io.*;
import java.net.*;
public class ClientTest {
public static void main(String[] args) throws IOException {
final int PORT_NUMBER = 44827;
final String HOSTNAME = "xx.xx.xx.xx";
//Attempt to connect
try {
Socket sock = new Socket(HOSTNAME, PORT_NUMBER);
PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
//Output
out.println("Test");
out.flush();
out.close();
sock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
The program works just fine when I use 127.0.0.1 or my internal IP for the hostname. But whenever I switch to my external IP address, it throws a java.net.ConnectException: Connection refused: connect error.
I purposely picked such an uncommon port to see if that was the problem, with no luck.
I can connect with no problems using telnet, but when I try to access the port with canyouseeme.org, it tells me the connection timed out.
I even tried to disable all firewalls and antivirus including the Windows default ones and the router firewall, with all ports forwarded and DMZ enabled, and it still says that the connection timed out. I use Comcast as my ISP, and I doubt that they block such a random port.
When I use a packet tracer, it shows TCP traffic with my computer sending SYN and receiving RST/ACK, so it looks like a standard blocked port, and no other suspicious packet traffic was going on.
I have no idea what is going on at this point; I have pretty much tried every trick I know. If anyone know why the port might be blocked, or at least some way to make the program work, it would be very helpful.
These problem comes under the following situations:
Client and Server, either or both of them are not in network.
Server is not running.
Server is running but not listening on port, client is trying to connect.
Firewall is not permitted for host-port combination.
Host Port combination is incorrect.
Incorrect protocol in Connecting String.
How to solve the problem:
First you ping destination server. If that is pinging properly,
then the client and server are both in network.
Try connected to server host and port using telnet. If you are
able to connect with it, then you're making some mistakes in the client code.
For what it's worth, your code works fine on my system.
I hate to say it, but it sounds like a firewall issue (which I know you've already triple-checked) or a Comcast issue, which is more possible than you might think. I'd test your ISP.
Likely the server socket is only being bound to the localhost address. You can bind it to a specific IP address using the 3-argument form of the constructor.
I assume you are using a Router to connect to Internet. You should do Port Forwarding to let public access your internal network. Have a look at How do you get Java sockets working with public IPs?
I have also written a blog post about Port forwarding, you might wanna have a look :) http://happycoders.wordpress.com/2010/10/03/how-to-setup-a-web-server-by-yourself/
But I still couldn't get this accessed over public IP, working on it now...
I had the same problem because sometimes the client started before server and, when he tried to set up the connection, it couldn't find a running server.
My first (not so elegant) solution was to stop the client for a while using the sleep method:
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
I use this code just before the client connection, in your example, just before Socket sock = new Socket(HOSTNAME, PORT_NUMBER);
My second solution was based on this answer. Basically I created a method in the client class, this method tries to connect to the server and, if the connection fails, it waits two seconds before retry.
This is my method:
private Socket createClientSocket(String clientName, int port){
boolean scanning = true;
Socket socket = null;
int numberOfTry = 0;
while (scanning && numberOfTry < 10){
numberOfTry++;
try {
socket = new Socket(clientName, port);
scanning = false;
} catch (IOException e) {
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return socket;
}
As you can see this method tries to create a socket for ten times, then returns a null value for socket, so be carefull and check the result.
Your code should become:
Socket sock = createClientSocket(HOSTNAME, PORT_NUMBER);
if(null == sock){ //log error... }
This solution helped me, I hope it helps you as well. ;-)

Categories

Resources