Unable to connect on socket across different networks - java

I am having trouble connecting my online application to others across another network. I am able to give them the hostAddress to connect when we are on the same network but when we are doing it across the internet the generated host address doesn't allow a connection, nor does using the ip address gotten from online sites such as whatismyip.com
My biggest issue isn't debugging this code, because it works over intra-network but The server doesn't see attempts when we try to move to different networks. Also, the test port I am using is 2222.
InetAddress addr = InetAddress.getLocalHost();
String hostname = addr.getHostName();
System.out.println("Hostname: " + hostname);
System.out.println("IP: " + addr.getHostAddress());
I display the host to the server when it is starting
if (isClient) {
System.out.println("Client Starting..");
clientSocket = new Socket(host, port_number);
} else {
System.out.println("Server Starting..");
echoServer = new ServerSocket(port_number);
clientSocket = echoServer.accept();
System.out.println("Warning, Incoming Game..");
}

If it works on your local lan but not across the internet then one or both peers are probably on a NAT'ed connection, meaning that the public IP address you see on the internet is not the same as the IP address of the machine you are trying to talk to. You would probably need to set up some kind of port forwarding to allow your app to connect.

The issue is probably firewall configuration.
Assuming you're testing this at home (it would usually be more complex from a university or company).
Usually you'll need to configure your router to let port 2222 open (you can also open port 5555 and tell your router to redirect to the host you want on your lan (there might be many), and port 2222).
To sum up:
other user ----> internet ----> [your modem] internet_IP -> [your router] lan_IP -> your computer lan_IP2
internet_IP is given by your ISP; find it here: http://www.whatismyip.com/
lan_IP: you defined in your router configuration. Typically: 192.168.0.1
lan_IP2: usually given to your PC by the router (DHCP). Find it by typing ipconfig (Windows) or ifconfig (Linux).
You need to tell your router to open port 2222, and route it to lan_IP2 on port 2222.
Configuring the router is usually done by connecting on its http interface: http://192.168.0.1

Some additional information might be helpful. Can you ping the machine from where you are? Are you attempting to go through a firewall? You say they work over localhost or local network - those are a bit different. Do you mean a network using local space (i.e. 10...* or 192.168.. or the like)? You say you are using a test ip of 2222 - that is not an ip address. Is that the domain of the address? Or is that the port number?

Related

Java : How to connect to ServerSocket using router public IP?

I'm trying to connect to server socket in java using my router's public ip,
first, I tried by simply configuring server socket to localhost, like this,
server = new ServerSocket(5000);
It is working on localhost but not working on trying internal ip 192.168.1.6
then, I tried configuring server socket to the internal Ip (saw this solution), code is as follows,
int backlog = 5;
server = new ServerSocket(5000, backlog, InetAddress.getByName("192.168.1.6"));
and it is working as my devices are connected to same network, I can connect to this Ip 192.168.1.6 from a device with Ip 192.168.1.5 on the same network but when I use public ip of my router from client side, connection is getting timed out, I've done port forwarding,
What am I doing wrong here? any help is appreciated, thanks in advance.
EDIT :
I came to about NAT-loopback (saw this solution) as I was trying to connect using public ip while being on same network so I tried different network but still it is not connecting, connection is getting timed out.
Firstly replace your port number by 8080, which is the default port for HTTP when you are not root. Then you have to open the port 8080 on your router to allow the client to connect.
Your server must be connected to the Internet and have a public IP address. Then the client can connect to this public IP address.

Java RMI cannot connect to server via WAN while it works in LAN

I'm working on a project using Java RMI and with a client-server implementation.
On the server side, this is how I initialize my server:
final String url = "localhost";
final int port = 8090;
LocateRegistry.createRegistry(port);
IServerGame serverGame = new ServerGame();
Naming.rebind("//"+url+":"+port+"/undercover", serverGame);
System.out.println("Server running at //" + url + ":" + port + "/undercover")
Undercover is the name of my application. We chose to use the port 8090
arbitrarily.
Now, here is how I initialize the connection client-side:
try {
server = (IServerGame) Naming.lookup("//"+address+":8090/undercover");
System.out.println("Connected to server " + address + ".");
} catch (Exception e) {
System.out.println("Connection failed.");
e.printStackTrace();
}
address is a string in the parameter of the method which initializes the connection and is the IP of the server. We ask the client to enter this IP to allow us to connect to different servers if we want.
When I run my application in local, whether I use localhost or my private IP 192.168.x.x as address, everything works fine. The client connects to the server and I can use the application. The problem is that when I want to use the application via WAN, sending the client to a friend and starting the server on my local machine, it doesn't work anymore. I get this error:
java.rmi.ConnectException: Connection refused to host: (private IP of host machine); nested exception is:
java.net.ConnectException: Connection timed out: connect
I've already checked a lot of posts in StackOverflow with the exact same problem and the usual answer is to either set the SystemProperty(java.rmi.server.hostname,"192.168.x.x") or do it via the -Djava.rmi.server.hostname in command line. I'm using Gradle to compile. I run the application via the run task. The client is a basic fx application too. None of this works unfortunately. I've also tried to open the port 8090 in my firewall but it doesn't solve the problem either.
Now maybe I'm doing this wrong. I've also tried to replace my private IP 192.168.x.x, which is IPv4 that I found via ipconfig in the command shell, with my public IP 79.95.x.x. But, again, it doesn't work.
I tried adding the SystemProperty(java.rmi.server.hostname,"192.168.x.x") like the first line of code that appears in the server code I showed you above.
I'm connected to internet via 4G. I don't have a box connection, so I can't really go to the box settings to allow certain ports, if that's ever a thing that could fix the issue.
EDIT :
So i've tried to switch from naming implementation in server-side to Registry implementation as it was suggested bellow but it didn't make any difference. As i thought it could be just a connection problem, i asked a friend to ping the server with telnet on the port 8090 and in fact it didn't work. He ran telnet [domain name or ip] [port] and the error was :
Unable to connect to remote host: Connection timed out
So the problem is that the external clients cannot reach my server or connect to the port. As i'm using 4G as internet connection as i mentioned above, any idea on how i could make the port reachable ?
Try using class java.rmi.registry.Registry rather than class java.rmi.Naming.
On the server side:
final int port = 8090;
Registry registry = LocateRegistry.createRegistry(port);
ServerGame serverGame = new ServerGame();
IServerGame stub = (IServerGame) UnicastRemoteObject.exportObject(serverGame, 0);
registry.bind("undercover", stub);
On the client side:
Registry registry = LocateRegistry.getRegistry("server host name or IP", 8090);
IServerGame serverGame = (IServerGame) registry.lookup("undercover");

Java - TCP connection

I am working now on simple program to send file through TCP using Java. I have a problem that I am not able to connect between computers ( I am testing application using router and local IP adresses).
I start connection by:
sendSocket = new Socket(sendIp, port);
and I am trying to recieve connection on next PC by:
servsock = new ServerSocket(port);
recieveSocket = servsock.accept();
where
port is 12222,
sendIp is 169.254.5.47 ( second computer that recieves)
and myIP is 192.168.0.52 ( computer that sends)
What I am doing wrong?
I always use the same port, and I see on TCPView that java app uses that port.
Maybe I assign wrong IP, or my firewall blocks somehow.
Best regards and thanks,
Chris
If this is a Windows network, the IP 169.254.5.47 means the host did not obtain a valid IP address from the DHCP. In a standard local network both addresses should be on the same class C range (192.168.0.*).
You have to first solve this physical issue with your network and test it using ping (each host should be able to ping the other and see replies).

JMX server and JConsole cannot connect

I have a JMX enabled application which creates RMI Registry by doing:
rmiRegistry = LocateRegistry.createRegistry(registryPort);
and then later on it creates JMXConnectorServer by doing:
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi://localhost:" + serverPort
+ "/jndi/rmi://:" + registryPort + "/jmxrmi");
connector = JMXConnectorServerFactory.newJMXConnectorServer(
url,
null,
ManagementFactory.getPlatformMBeanServer());
connector.start();
My problem is that I cannot connect to this JMX Server from a remote host using JConsole. I've followed the instructions for debugging/tracing JConsole and I can see that the problem is that JConsole tries to connect to a bogus IP address that it must have gotten from the Registry. Ok, it isn't exactly bogus because it happens to correspond to a virtual network interface I have on the JMX Server host machine. How on earth does JMX pick that up?
A netstat on my application reveals that both the serverPort and the registryPort are bound on the wildcard interface (on both IP4 and IP6) which is as expected since I haven't supplied socket factories. Basic connectivity works from the remote host, i.e. I can get the telnet test to pass on both ports.
I would have assumed that I would have to change 'localhost' in the JMXServiceURL to the name of my host (as other hosts sees it, not how it sees itself) but that doesn't help.
What do do ?
UPDATE1
After some more investigation I'm pretty sure this 'bogus IP address' comes because RMI just picks the first IP it finds on its own host and then uses that as its 'call-me-back' address. It then happens to find that virtual NIC that exists on this host. That's really not want I want. I want to be able to control explicitly the RMI 'call-me-back' address.
Welcome to RMI hell.
The end point resolve himself and send back to jconsole the ip to use.
If you can try to use JMXMP : http://meteatamel.wordpress.com/2012/02/13/jmx-rmi-vs-jmxmp/.
You can also try java.rmi.server.hostname :
http://docs.oracle.com/javase/7/docs/platform/rmi/spec/rmi-properties2.html

Java Socket Bind Error

I have been having trouble about socket usage in java. First of all, let me explain what I want to do with sockets in java. I want to connect my laptop over the Internet via it. My laptop has a server and a client must connect over the internet. Because I have a router to handle my local network and I do not want to lead a port on the router to my laptop, I need to follow the path "internet->router->localNetwork->mylaptop". The problem is I have found a way to use both the internet ip address and the local ip address; However, it throws an exception : "Exception in thread "main" java.net.BindException: Address already in use"
The code I try is :
InetAddress addr = InetAddress.getByName("XXX.XXX.XXX.XXX");
InetAddress local = InetAddress.getByName("YYY.YYY.YYY.YYY");
Socket socket = new Socket(addr, 1111, local, 1111); // The line I have got exception
With leading router port to my laptop, I can run this code for the similar purposes:
Socket socket = new Socket("XXX.XXX.XXX.XXX", 1111);
*Xs stand for internet ip address
*Ys stand for local ip address
*Codes are belongs to client side of code
As far as I understand, you have a router with Internet (WAN) IP XXX.XXX.XXX.XXX with NAT, and you have a laptop with Local (LAN) IP YYY.YYY.YYY.YYY connected to the router, and you assume that
Socket socket = new Socket(InetAddress.getByName("XXX.XXX.XXX.XXX"), 1111, InetAddress.getByName("YYY.YYY.YYY.YYY"), 1111);
Will connect to the laptop. That is not correct.
Documentation of the constructor of Socket class you are using tells:
Creates a socket and connects it to the specified remote host on the specified remote port. The Socket will also bind() to the local address and port supplied.
That is not what you want.
You can't connect to a device behind NAT like this. You have to "lead a port on the router".
You don't need to specify the local address:port of the Socket, and you are doing so incorrectly. Remove the last two parameters.

Categories