Pyro4 connect with java - 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.

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.

How to figure out to which server a client connected to

I'm using Netty to build a client-server network communication. Is it possible to find out to which app a client has connected to in case of success?
It's the following problem I try to solve: If a Tomcat Server is listening to port 8080 my client app successfully connects to the "server". Looks like it doesn't matter who is listening to the port.
How can I find out if my server app is currently started and listening to the port instead of e.g. Tomcat?
This is the connection code of the client:
public void run(){
//disconnectTest();
createBootstrap( new Bootstrap(), new NioEventLoopGroup(), true);
}
public void createBootstrap( Bootstrap b, EventLoopGroup eventLoop, boolean initialAttempt){
mWorkerGroup = eventLoop;
try {
b.group(mWorkerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
.handler(new ClientChannelInitializer());
logger.info("Connecting client...");
b.connect(mHost, mPort)
.addListener( new ConnectionListener(this, initialAttempt));
} catch (Exception e) {
logger.error("Failed to connect client to server '" +mHost +": " +mPort +". Error: ", e);
}
}
Snippet from the ConnectionListener:
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
System.out.println("success");
}else{
System.out.println("error");
}
}
EDIT:
If you want check the availability of the server withing the client App, you can use certain tools that Java7 can give us, for example, using this code:
private static boolean available(int port) {
try (Socket ignored = new Socket("localhost", port)) {
return false;
} catch (IOException ignored) {
return true;
}
}
This does not have to be a specific function Netty. More info here:
Sockets: Discover port availability using Java
Enjoy.
To check it outside you client app:
To test the server status I use the Hercules software client.If you know that server will respond someting, using hercules you can send a dummy data y wait the server response.
How you can see, Hercules, allows too makes a ping to the server :)
Hope it helps.

Java RMI proxy-casting issue

I'm trying to get a RMI program to work. So far, the server starts up correctly but the client fails casting the remote object to the interface.
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException:
com.sun.proxy.$Proxy0 cannot be cast to MonitorClient.InterfaceMonitor
All other answers I've found are for cases where the end user has cast the equivalent of InterfaceMonitorImpl (unknown to the client) instead of the Interface instead. This is not my case and I'm really at a loss here — RMI is nightmare-ish.
Server side
Main:
InterfaceMonitor obj;
try {
LocateRegistry.createRegistry(1099);
InterfaceMonitor stub = (InterfaceMonitor) UnicastRemoteObject.exportObject(new InterfaceMonitorImpl(), 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("imon", stub);
System.out.println("Server ready");
} catch (RemoteException | AlreadyBoundException ex) {
System.out.println("Server error: " + ex.toString());
}
InterfaceMonitor.java:
public interface InterfaceMonitor extends Remote {
int checkAge() throws RemoteException;
}
InterfaceMonitorImpl.java:
public class InterfaceMonitorImpl implements InterfaceMonitor {
public InterfaceMonitorImpl() throws RemoteException {
}
#Override
public int counter() throws RemoteException {
return 10;
}
}
Client side
try {
Registry reg = LocateRegistry.getRegistry(null);
InterfaceMonitor im = (InterfaceMonitor) reg.lookup("imon");
int counter = im.counter();
System.out.println("Counter: " + counter);
} catch (NotBoundException | RemoteException ex) {
Logger.getLogger(MonitorGUI.class.getName()).log(Level.SEVERE, null, ex);
}
The InterfaceMonitor.java is also on the client side.
Thanks for your time!
Obviously you must have two copies of InterfaceMonitor: one in MonitorClient and one in what may be something like MonitorServer. That makes two different classes. Not two copies of the same class. The class name, package, method declarations, inheritance, ... all have to be the same.

Server RMI stop automatically when I start it

I'm frensh so sorry for my english.
I'm trying to start a server rmi but the application stop whitout error :
Here my code:
public class Server {
public static void main(String[] args) {
try {
RemoteFunction skeleton = (RemoteFunction) UnicastRemoteObject.exportObject(new FunctionImpl(), 0);
int port = Integer.parseInt(Jndiprop.getString("port"));
Registry registry = LocateRegistry.createRegistry(port);
registry.rebind(Jndiprop.getString("url"), skeleton);
System.out.println("Rmi start");
} catch (Exception e) {
e.printStackTrace();
}
}
}
the port and the url are ok.
Someone can help me ?
You must store the Registry in a static variable. Otherwise it can be garbage-collected, which leads to a train of events that allows the whole JVM to exit.

RMI - work in the same machine, not in LAN

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

Categories

Resources