I am a researcher at University and I'm trying my hand at a bit of amateur java2 programming.
I've been working through the KnockKnockServer/Client Java2 tutorial to send strings from one program to another using Java Sockets.
http://download.oracle.com/javase/tutorial/networking/sockets/clientServer.html
Full source can be downloaded there and it compiles nicely and is a great example of using IP's to get two programs to talk to each other in Java.
This works fine when I use both the server and the client running on the same machine and the machine name as "localhost"
kkSocket = new Socket("localhost", 4444);
And it also works at home when I use it on my home network with a InetAddress:
InetAddress myaddress = InetAddress.getByName("129.11.138.64");
kkSocket = new Socket(myaddress, 4444);
However when I try to do the same on the university machines it doesn't work because they are behind some kind of proxy despite the fact that the two machines are next to each other and plugged into adjacent ethernet ports.
Question:
How to I work out how to get the two machines to speak to each other, when I don't have full control of the network they are on? I can't even work out how to get them to ping each other. I have visited "www.whatismyip.com" to get the external ip's of each machine but that doesn't work, and I've looked at the next work adapters ip and the gateway they are on but still I can't get them to talk to each other.
Any ideas.
Thanks!
It sounds to me like your network is blocking traffic on port 4444. Try a different port, or confirm that port 4444 is allowed.
There are several different parts to this problem:
1) Can the two machines connect to each other?
You can test this from the command line with the "ping" command which is available in both Windows and *nix. Ping tests for the existence and reliability of a connection to the named machine.
2) Could the route be filtered?
Just because you can ping a machine, doesn't mean there is no firewall or proxy between them. You can find the route taken between the two machines with the "tracert" command. The more steps in the route, the more things that might stop your signal
3) Is Java firewalled?
Just because it is installed, does not mean it has open network access. Try fetching a few URLs or similar to see if Java has network connectivity.
4) Is the port blocked?
A port could be blocked in two ways: some other application is using it, or a firewall is limiting listening ports. If the former, Java will not be able to attach a Socket to the port. If the latter, try a different port. There is nothing to stop you running 10000 clients simultaneously and seeing if you can connect to any of them.
5) How do you do this in Java?
Ping can be implemented by InetAddress.isReachable().
6) What should I say to the angry Network Admin guy who has just turned up?
"I'm not port and network scanning! Honest!" Hunting for usable ports is a basic hacking operation. Some workplaces have automatic tools to check for it and will view it as inappropriate.
Even i cannot ping two machines at my work place.
you need to change the network preferences or try the following:
(instructions for IE)
Go to tools-> internet options -> lan settings -> advanced.
Add exceptions to the field: "Do not use proxy server for addresses beginning with:"
enter the networks ip starting numbers, for eg if your network has ip adds starting with 10.--.--.-- write 10.* in the field.
You need to make sure that each machine knows about the other's private IP address on the LAN (see the ipconfig or ifconfig command). It changes (nearly) each time the devices are connected on the LAN, and sometimes even while they are connected on the LAN.
www.whatismyip.com won't help you, because it will only give you the public IP address of the router/NAT which is closest to that server. There is no guarantee it is also the closest one to your devices. Even if it were, this information would be useless, because you (most often) can't predict how the NAT will translate your private IP address into public IP address.
Even if you could 'guess' that information, there is a possibility that the router/NAT might not let you use this translation behind it (i.e., on the LAN).
To summarize it, make sure you use the proper private IP addresses assigned to your devices and make sure that no router or firewall is blocking traffic over the considered port.
Related
I'm planning on writing a relatively simple client-server socket program in Java, where the server will run on one machine and the client on another machine (both wired on the same network).
Link two computers with Socket in Java.
From the answer to the above question, I believe that I will need to port forward (not an issue as I know how), but this does, however, go against my intuition as I am under the impression that port forwarding would only be necessary if I needed to connect to a service/machine/whatever on my network from a remote machine (not on the network).
So my question is, do I need to port forward for communicating between two machines on a local network? If yes, why?
If the machines are in the same network, you don't need to configure port-forwarding. Even if the machines are in different networks, you don't need to configure port-forwarding, assuming those machines have routable IP addresses (and there is no firewall blocking that access).
Port-forwarding is only relevant when communicating to - for example - a home network that has a single IP address, where there are multiple machines on an internal network, and the local router that is visible to the internet needs to perform NAT (Network Address Translation) to map between the local network and the big bad internet. Port-forwarding makes sure that an internet visible port is forwarded to the IP address of a machine on the internal network.
What you do need to take into account is the possibility that local machine firewalls (e.g. Windows Defender) may block access without explicitly whitelisting the application and/or port.
For a small java game I made, I would like to be able to play it with two computers in the same (home) network. I think I will use RMI and am now trying with computer on ipaddress 192.168.2.3.
I know I can search for a registry on this ipaddress on my other computer at 192.168.2.6, but I would like to show a list of all ipaddresses in the network my computer is connected with. Prefferably only if they actually host a game.
Now I tried some questions here on stackoverflow:
How to enumerate IP addresses of all enabled NIC cards from Java?
How can I find all locally bound IP addresses in Java?
How to get a list of IP connected in same network (subnet) using Java
Why does InetAddress.isReachable return false, when I can ping the IP address?
,but I don't think I need all my computer network interfaces and InetAddress.isReachable() always seem to result to false (even though I can ping via cmd and I have firewall turned off) and calling a commandline
"ping -n 1 192.168.2.i" for all i, where 0<=i<=255,
always exits normal, so it results always in true.
What is the best way to get a list of ipaddresses of computers in the same network as the computer the JVM runs on?
With the linked answers, you should be able to filter the available interfaces down to a few possible options (i.e. interfaces that are up, no loopback, have an IPv4 address, etc.).
To discover game hosts, you can do something like the following.
Let the game hosts listen for UDP broadcasts on a specific port.
Let the clients send out a UDP broadcast to the broadcast address of each of the remaining interfaces from above. The broadcast address can be determined by getBroadcast() in class InterfaceAddress.
The host replies, to let the client know it is waiting. When using UDP, the hosts IP is in the received DatagramPacket. When using TCP, the hosts IP can be determined from the Socket.
Then the client can use the address of the host to establish a direct connection and/or set up RMI.
Edit: I found this blog post, which includes code that does more or less what I described.
I've been studying how to use sockets to make two java programs communicate.
Now, on each example I've gone through, they've always placed the "server side program" on the same computer on which the "client side program" was, and of course the IP set was either 127.0.0.1 , or simply "localhost".
Now, my question is:
how do I get to communicate the two programs if one is on a computer, and one on another?
I've tried to set the IP as the one my computer has when connected to internet (the one I found simply by googling "what's my IP"), but that way it doesn't seems to work.
Can anyone explain me better how I can make it work?
The computers will need to be on the same network or their IP address will need to be accessible to the internet. If you are in windows, you can find the local IP address by opening a cmd window (press windows key + R then type cmd) and running ipconfig. On linux (maybe it works on Mac as well) you can run ifconfig in a terminal. If your computers are on the same local area network you should be able to use the IP addresses indicated by those commands.
If they are not on the same local area network, a router in between the computers may have a firewall policy which is blocking the connection.
I have spent some time learning about socket programming in Java and have managed to make a couple of simple apps that utilize sockets. (instant messenger, tic-tac-toe, basic things) For my programs I used a client-server relationship with ServerSocket and Socket classes. So far I have been testing all my games on the same machine, meaning the client and the server both run on the same machine and the socket ip I am using is 127.0.0.1. Now I want to make a LAN game using the same logic. One computer will be the server and another will be the client.
The thing I wanted to ask, and pardon me if this is a stupid question, I am not really educated about networks and whatnot, but under what conditions can I establish a socket connection between two machines. What I mean is, I run my socket server on one computer and I want the socket on another computer to connect using the first computer's ip. Say, for example my ip is "192.1.1.4" I want to be able to connect to that computer. Is it possible to establish a connection like this between just any two computers in the world? I know "lan" stands for "local area network" but I am quite ignorant on it beyond that. Sorry it it is a dumb question and I can clarify it if someone needs me to.
Basically, what criteria must be met on two machines for me to be able to establish a socket connection between them using a Java program?
You can make a TCP/IP connection between:
Two machines in the same LAN (private IP)
Two machines with public IP (internet)
A machine in a LAN and a machine with public IP provided that the connection is openned from the LAN to the public IP
You can't open a direct TCP/IP connection to a machine inside a LAN from outside the LAN, unless the gateway is configured to redirect the connections to a specific port to that machine.
On an internal network you do just what you said, client connects to server using server's ip address or hostname on the given port.
over the internet can be tricky because of firewalls and NAT. For example, your computer's ip address on the home network is probably somewhere along the lines of "192.168.0.xxx" - but if you go to: http://www.whatismyipaddress.com you'll see that your internet facing ip address is completely different. What you'll see is basically your router's IP address on the internet (WAN).
So basically, the server will have to setup port forwarding on their router for your game's port to his computer. Then he will have to provide the clients with his internet facing ip address for connection.
The main criterion for establishing a connection - ignoring a multitude of possible factors such as firewall configuration, etc. - is that the two machines are simply on the same network. You may be aware that an IP address starting with 192.168.. always refers to a computer on a local network, which is the situation you are asking about, so if you have two computers connected on a local network (e.g. via a router), and you know the IP address of each machine, then it really is as simple as that - you connect in the same manner you have been using up until now. In fact, the same applies on the internet - even if you have two machines set up on different sides of the world and you know their IP addresses (again, ignoring potentially more significant firewall issues), the process is exactly the same. This is precisely the reason that the internet has proved so scalable, as the process of locating a machine with a particular IP address is handled by the lower layers of the network stack.
tl;dr: It's the same as what you are doing already, just with the appropriate IP addresses.
you can use a public IP address and you don't have to change anything about your own address, this is handled by your router that connects to the internet. What you do have to consider is your firewall settings. The ports you are using in your socket should be added to your 'allowed' list. Normally "established" traffic is allowed by default. This means that you need to allow your incoming ports # serverside to go to your server.
This is what I'm planning to do. Suppose there are 2 machines A and B. I need to create an application by which machine A can send data to Machine B, using Java SE.
I know that to make a connection you need to create an object of serversocket class and use the accept() method as
In Machine B:
ServerSocket ss=new ServerSocket(12000);
while(true)
{
Socket s=ss.accept();
.
.
.
.
}
In Machine A:
Socket s=new Socket("<Machine B's IP Address>",12000);
.
.
.
.
Here's the problem.
Suppose if Machine B's IP address is assigned dynamically with DHCP, ie it can change each time the machine reboots.
Is there any way by which the Java Pgm in machine A can recognize the IP address of B without the user typing it manually???
Hoping that you the question is clear.
Waiting for replies!
Most DNS servers have a mechanism that allows the DHCP server to make dynamic updates to the local (internal) zone. If you have this feature at your disposal, then you can just use DNS names, and let the systems guys make sure that the DNS records are up-to-date with the DHCP leases.
A similar DNS-based approach could be accomplished on the wider internet using a DDNS service like dyndns.
If you can't use DNS, then you're stuck with a UDP broadcast-based approach. This is the same mechanism that protocols like DHCP, bonjour, and SMB use to find other computers on the local network without knowing their addresses; and this approach will only work in the same contexts where those technologies work (typically, only within the local network, and definitely not across the greater internet).
In java, you would accomplish UDP broadcast messaging via the DatagramSocket class.
Quoting the api docs:
UDP broadcasts sends are always enabled on a DatagramSocket. In order to receive broadcast packets a DatagramSocket should be bound to the wildcard address. In some implementations, broadcast packets may also be received when a DatagramSocket is bound to a more specific address.
Example:
DatagramSocket s = new DatagramSocket(null);
s.bind(new InetSocketAddress(8888));
Which is equivalent to:
DatagramSocket s = new DatagramSocket(8888);
Both cases will create a DatagramSocket able to receive broadcasts on UDP port 8888.\
If your two machines are located at disparate locations on the internet, and you can't use a DDNS service (like dyndns, mentioned above), then your best bet is to build a central registration server. This would be a simple server (could even be a web service) that runs at a known address on the internet. Each of your client machines would register with the central registration server, thus the central registration server would know the IP addresses of both machines. Then each machine could request the other's address via the central registration server. You'd have to put some thought into to security in order to protect against malicious "poisoning" of your registry, but otherwise, this would be fairly straight forward.
EDIT:
I just discovered JXTA. It's a set of tools for building java applications with peer-to-peer networking features. I don't have any direct experience with it, but it looks like it would accomplish what you're looking for (and probably save you a lot of work over having to build it all from scratch).
In fact, it looks like the subproject p2psockets does exactly what you want.
In Java you can compute the IP address of machine by host name, Here is the code
java.net.InetAddress inetAdd = java.net.InetAddress.getByName("www.ibm.com");
System.out.println("IP Address is : " + inetAdd.getHostAddress());
Use this code to get the changed IP address every time machine reboots