ill try to explain my setting.
Setting:
i run 1 "server"(note: not rmi server) who is always up.
When i run 1 client, the client creates an rmi host like so:
String bindLocation = "//localhost/ntn";
try {
registry = LocateRegistry.createRegistry(1099);
Naming.bind(bindLocation, ntn);
} catch (MalformedURLException | AlreadyBoundException e) {}
And the server starts acting as a RMI client like so:
try {
name = "//localhost/ntn";
ntnI = null;
ntnI = (NodeToNodeInterface) Naming.lookup(name);
ntnI.serverAnswer(k);
k++;
} catch(Exception e) {
System.err.println("FileServer exception: "+ e.getMessage());
e.printStackTrace();
}
This all works. But after that the client has received the "server answer" it unbinds like so:
try {
Naming.unbind(bindLocation);
UnicastRemoteObject.unexportObject(registry,true);
} catch (NotBoundException e) {}
Now if i Open a seccond client(same code as client 1) it again start to act as a RMI server on the same name and port. if this is set up de same function runs on the server and gives the following error:
java.rmi.NoSuchObjectException: no such object in table
wich points to the line:
ntnI = (NodeToNodeInterface) Naming.lookup(name);
How do i reinitialise it? or how to fix this?
Normally the RMI server is perfectly setup before the server(RMIclient) uses the serverAnswer function.(and it works teh first time)
Don't unexport the registry, and don't create it when you bind. Create it first and leave it there for the life of the JVM. Otherwise there is nothing for Naming.lookup() to talk to.
Related
I am experiencing an error which I am at a loss to explain. I feel like I'm so close but I just can't seem to get a connection.
I have setup two RMI server objects on a remote server and I want to connect to and use these. I am able to connect to the RMIRegistry on the server on port 1099 and with the call Registry.list() I get the correct names of the stubs which are setup on the server.
Now for my code...
Server object 1
Registry registry = null;
try {
registry = LocateRegistry.createRegistry(1099);
} catch (RemoteException e){
System.out.println("Registry already exists - connecting...");
try {
registry = LocateRegistry.getRegistry(1099);
String[] objects = registry.list();
for (int n=0; n<objects.length; n++){
System.out.println(objects[n]);
}
} catch (RemoteException ex) {
ex.printStackTrace();
System.out.println("RMI registry connection fail.");
System.exit(1);
}
}
BioBingoLogic bb = null;
bb = new BioBingoLogic();
BioBingoInterface bbStub = null;
try {
bbStub = (BioBingoInterface)
UnicastRemoteObject.exportObject(bb, 9753);
} catch (RemoteException e){
e.printStackTrace();
System.out.println("RemoteServer export fail.");
System.exit(1);
}
try {
registry.rebind("BioBingoServer", bbStub);
} catch (RemoteException e){
e.printStackTrace();
System.out.println("Registry rebind fail.");
System.exit(1);
}
Server object 2
Completely the same as Server object 1 only exported on port 9754 and called "DatabaseServer".
Output
My output from these two objects is in the following picture:
Output from running the two server objects.
Client side
The server objects work as I expect them to. It is the Client which doesn't seem to be able to connect to the individual server objects.
System.out.println("Creating RMI Registry stub.");
Registry remoteRegistry = null;
try {
remoteRegistry = LocateRegistry.getRegistry("biobingo", 1099);
String[] objects = remoteRegistry.list();
System.out.println("\nObjects in stub:");
for (int n = 0; n < objects.length; n++) {
System.out.println(objects[n]
}
System.out.println();
System.out.println("Connecting to BioBingoServer object.");
try {
game = (BioBingoInterface) remoteRegistry.lookup("BioBingoServer");
db = (DatabaseInterface) remoteRegistry.lookup("DatabaseServer");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Stub not found.");
System.exit(1);
}
} catch (RemoteException e) {
e.printStackTrace();
System.out.println("Registry not found.");
System.exit(1);
}
System.out.println("Connected to BioBingoServer.");
System.out.println("Connected to DatabaseServer");
biobingo is the IP of the remote server registered with the alias in my hosts file.
Output
This is where the problem arises....
I get the output in the following picture:
Output from client side application
It should be understood from the picture, that I never get an exception of any kind. It just hangs on the call Registry.lookup() until it, I suppose, gets a timeout from the server and executes the next part of the client code - calls to the server object then throws a RemoteException.
It should be noted that the remote server is behind a NAT, however, the NAT and its firewall is setup to allow all incoming TCP traffic, from all IP's, on all the specified ports; 1099 + 9753 + 9754.
I have also verified that the ports are indeed open with a port scanner.
This is where I am at a loss...
Any suggestions to what is preventing me from connecting to the server objects, when I am entirely able to connect to the RMIRegistry?
Any help is greatly appreciated - thank you!
---------------------------------------------
EDIT
---------------------------------------------
I tried running the server objects and client with the java vm option:
-Dsun.rmi.transport.tcp.logLevel=VERBOSE
The following picture shows the output and includes description of the flow and where the possible error occurs:
output with java vm option.
Client output
No output, just a 3 minute delay on Registry.lookup(). Afterwards the following code is executed and then on function calls to the RMI stub there’s a 3 minute delay followed by a ConnectException saying *connection timed out to 10.230.56.71` (which is the local IP of the server, although I’m connecting to it’s global IP - so it seems that my call does find it’s way to the NAT which the server is behind).
Server output
Nothing, really.
I have a client that I want to try to continuously connect to a server until a connection is established (i.e. until I start the server).
clientSocket = new Socket();
while (!clientSocket.isConnected()) {
try {
clientSocket.connect(new InetSocketAddress(serverAddress, serverPort));
} catch (IOException e) {
e.printStackTrace();
}
// sleep prevents a billion SocketExceptions from being printed,
// and hopefully stops the server from thinking it's getting DOS'd
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
After the first attempt, I get a ConnectionException; expected, since there is nothing to connect to. After that, however, I start getting SocketException: Socket closed which doesn't make sense to me since clientSocket.isClosed() always returns false, before and after the connect() call.
How should I change my code to get the functionality I need?
You can't reconnect a Socket, even if the connect attempt failed. You have to close it and create a new one.
I want to check whether server is still connected to the client or not before reading from stream. How to do that in java? My current code is as below.Will this check only for client socket?
public void receiveResultFromServer() {
try {
while(!clientSocket.isClosed()) {
try{
Object obj = inStream.readObject();
if (obj instanceof Command) {
ConnectionManager.parseCommand((Command) obj);
} else if (obj instanceof CommandExecResult) {
ConnectionManager.parseCommandExecutionResult((CommandExecResult) obj);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
} catch(Exception e) {
e.printStackTrace();
}
Knowing connectivity just before reading streams is not good. Instead design a heartbeat mechanism.
Algorithm :
a) design two commands using enum "SEND_BEAT" and "RECEIVE_BEAT" on both client and server.
b) Now as soon as your server starts, start a thread that sends a signal from server to client(HandShake Protocol) using the the commands and client will respond back to the signal to the server.
c) this sending signal job can be scheduled at regular interval of time, using Java Timer and TimerTask classes available for e.g.
scheduleAtFixedRate(new RunTimer(), 5000, 1000);
d) on the basis of response, maintain the status of client on the server.
e) Now you can use status for checking the connectivity between the client and server.
f) In fact, you can even design a re-connect mechanism which will try for certain number of times before final update.
h) Also you need to maintain the state as checkpoint as per your need.
hopefully above algo fulfills your demand.
If the peer has disconnected, your code will throw am EOFException. If there has been a network failure it might block forever, so you might want to consider using a read timeout, which would throw a SocketTimeoutException.
I try to check if port 80 is available using the following method :
Sockets: Discover port availability using Java
I have a Java application that checks if port 80 is available, if so, it runs a small web server listening on port 80. It works great to detect if another Java application listens on port 80, e.g. if I run my application two times, the second instance will correctly tell me that the port 80 is being used.
The problem is that I have WAMP running and listening on port 80, and that if I run my Java application after I started WAMP, it won't tell me that the port 80 is busy. It seems that it only tells me if another Java application uses the port 80.
That goes beyond my understanding ... any help is greatly appreciated!
Code snippet:
int port = 80;
if(!Connection.isPortAvailable(port)) {
logger.info("Port " + port + " is already in use");
}
// in Connection class
public static boolean isPortAvailable(int port) {
ServerSocket ss = null;
DatagramSocket ds = null;
try {
ss = new ServerSocket(port);
ss.setReuseAddress(true);
ds = new DatagramSocket(port);
ds.setReuseAddress(true);
return true;
} catch (IOException e) {
} finally {
if (ds != null) {
ds.close();
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
/* should not be thrown */
}
}
}
return false;
}
The correct answer to all questions of this nature is to try to use it and catch the exception. Not try to see if it's available and then try to use it and still have to handle the exception, which has several obvious problems:
There is a timing window between 'see' and 'try' during which the situation can change (both ways).
You still have to catch failures in the 'use' part anyway.
It is basically just trying to predict the future. This is supposed to be computer science, not fortune-telling.
This applies to most values of 'it', including network ports, files, any resource really.
I was able to reproduce your problem by running WampServer (verified that it was running by visiting localhost:80) and running a minimal java program given your example code.
The code in the try block did not throw an exception when WampServer was running. However, modify the first few lines of the try block like this
ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", port));
and isPortAvailable will properly detect when WampServer is running and when it is not. Using "0.0.0.0" instead of "127.0.0.1" didn't work with WampServer, but did properly detect when IIS was running. You can check both by closing the first socket
ss = new ServerSocket();
ss.bind(new InetSocketAddress("0.0.0.0", port));
ss.close();
ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", port));
I am testing a chat application for number of users. So what I am trying is as follows:
I am trying to run my chat application by login for chat for only one user for 1000 times in for loop. here is my part of code .
public void LoginChatConnect() {
try {
// while(true){
for(int i=0;i<1000;i++){
System.out.println("inside loginChatLogin");
String userId = "Rahul";
String password = "rahul";
sockChatListen = new Socket("localhost", 5004);
// /sockChatListen.
dosChatListen = new DataOutputStream(
sockChatListen.getOutputStream());
disChatListen = new DataInputStream(sockChatListen.getInputStream());
dosChatListen.writeUTF(userId);
dosChatListen.writeUTF(password);
// System.out.println(dosChatListen.toString());
dosChatListen.flush();
// sockChatListen.close();
boolean b = sockChatListen.isClosed();
System.out.println("connection open**********************" + b);
sockChatListen.close();
System.out.println("connection closed**********************" + b);
count++;
System.out.println("count" + count);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In above code I am just trying to login for only one user for 1000 times. But after certain login it is giving me this socket error.
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
Here I am trying to create a connection with a single port 5004. why I am getting error after 100+ successful connections(login).?
How should I recover this problem?
Any suggestions will be helpful.
What I understand from your post is that you want to simulate 1000 users logging to the chat server concurrently. I believe you are trying to test the load on your chat server.
However, from your code, I see that you are establishing and closing the socket connection every time in the loop. This is similar to 1000 users waiting in a queue and attempting to login to the server one after the other. This does not simulate the concurrent load but a 1000 sequential calls to the server and would not be appropriate to load test your server.
My comments are based on the above stated understanding. Please calrify if this is not the case.
Regarding the exception you get, I have no idea why it should not work after 100+ attempts. May be you need to check your server side code to figure out the problem.