How to list all computers in network? - java

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.

Related

How does one connect with another machine with IP address?

So I've been learning Java Sockets for some time now, and all my codes are tested basically with a localhost (my own computer).
I was wondering if say I have another machine in another country, does the simple client-server connection still work? (My codes are peer-to-peer connection).
Is it that simple with just IP address and Port?
Sorry this question seems weird but back in the days when I was playing online games, simply putting "connect 'ip address' " didn't always work.
I was wondering if say I have another machine in another country, does the simple client-server connection still work?
Possibly yes, possibly no.
Is it that simple with just IP address and Port?
Possibly yes, possibly no.
If the IP address is a public IP address, AND there are no firewall issues, then it should work. But that is a BIG IF ......
If the remote IP address you are trying to connect to is not a public IP address, then there is no way that packets can be routed to it. No connection is possible.
If there are firewalls between your machine and the remote IP, they need to let packet for that IP / protocol / port through, otherwise connections will fail.
IMO, you would be better off doing some basic research / reading on how IP-based networking works before you ask questions like this.
(My codes are peer-to-peer connection).
That is at the next level up the networking stack. Peer-to-peer is implemented on top of transport-level protocols like TCP/IP and UDP/IP. If the transport level doesn't work, then application level protocols won't either.

Java - Connecting two machines on same network

I want to simply connect two machines on the same network via a TCP Server/Client socket connection.
Right now, I need the IPv4 address from the machine hosting the server in order to connect the client.
localhost works fine when I'm running the server and the client on the same computer, but that's not very useful.
Is there any way around having to manually punch in the IPv4 of the host computer?
Thanks, this will probably clear up a lot of confusion.
Use a broadcast to send all clients a message. (this could contain the servers IP but think about that! it could be a security issue)
There are good examples on sending broadcast messages with java
Broadcasting to Multiple Recipients
If you know the name of the hosts, then you can also pass these names in a config file and use getaddrinfo() to get the IP address of the host: http://man7.org/linux/man-pages/man3/getaddrinfo.3.html . Since hostnames do not chnage frequently, this should provide good improvement as compared to manually punching the IP address.

LAN Game in Java

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.

Java UDP hole punching example - connecting through firewall

Lets say I have two computers.
They know each others public and private IPs via ice4j.
One client listening and the other one sending some string.
I'd like to see this happen via UPD hole punching:
Let A be the client requesting the connection
Let B be the client that is responding to the request
Let S be the ice4j STUN server that they contact to initiate the connection
--
A sends a connection request to S
S responds with B's IP and port info, and sends A's IP and port info to B
A sends a UDP packet to B, which B's router firewall drops but it still
punches a hole in A's own firewall where B can connect
B sends a UDP packet to A, that both punches a hole in their own firewall,
and reaches A through the hole that they punched in their own firewall
A and B can now communicate through their established connection without
the help of S
Could any one post pseudo examples of how to go about doing hole punching through symmetric NAT? Assuming there will be server S that will help to guess the port numbers and establish connection between the client A and B.
It would be nice if you accounted for double NAT as well.
NOTE:
You can use STUN to discover the IP and Port but you have to write your own code that would send the IP:Port to your server via keepalive technique.
Once one client identifies the other via unique ID on the server it will be provided with the other's client IP:port info to UDP hole punch the data it needs to send and receive.
Little update:
There is library that is showing up on the horizon for java check it out:
https://github.com/htwg/UCE#readme
This example is in C#, not in Java, but the concepts of NAT traversal are language-agnostic.
See Michael Lidgren's network library which has NAT traversal built in.
Link: http://code.google.com/p/lidgren-network-gen3/
Specific C# File Dealing with NAT Traversal: http://code.google.com/p/lidgren-network-gen3/source/browse/trunk/Lidgren.Network/NetNatIntroduction.cs
The process you've posted is correct. It will work, for only 3 out of 4 general types of NAT devices (I say general because NAT behavior isn't really standardized): Full-Cone NATs, Restricted-Cone NATs, and Port-Restricted-Cone NATs. NAT traversal will not work with Symmetric NATs, which are found mostly in corporate networks for enhanced security. If one party uses a Symmetric NAT and the other party doesn't, it's still possible to traverse the NAT but it requires more guesswork. A Symmetric NAT to Symmetric NAT traversal is extremely difficult - you can read a paper about it here.
But really, the process you've described works exactly. I've implemented it for my own remote screen sharing program (also in C#, unfortunately). Just make sure you've disabled Windows firewall (if you're using Windows) and third-party firewalls. But yes, I can happily confirm that it will work.
Clarifying the Process of NAT Traversal
I'm writing this update to clarify the process of NAT traversal for you and future readers. Hopefully, this can be a clear summary of the history and the process.
Some Reference Sources: http://think-like-a-computer.com/2011/09/16/types-of-nat/, and http://en.wikipedia.org/wiki/Network_address_translation, http://en.wikipedia.org/wiki/IPv4, http://en.wikipedia.org/wiki/IPv4_address_exhaustion.
IPv4 addresses, with the capacity to uniquely name approximately 4.3 billion computers, have run out. Smart people foresaw this problem, and, among other reasons, invented routers to combat IPv4 address exhaustion, by assigning a network of computers connected to itself 1 shared IP address.
There are LAN IPs. And then there are WAN IPs. LAN IPs are Local Area Network IPs which uniquely identify computers in a local network, say the desktops, laptops, printers, and smartphones connected to a home router. WAN IPs uniquely identify computers outside of the local area network in a wide area network - commonly taken to mean The Internet. So these routers assign a group of computers 1 WAN IP. Each computer still has its own LAN IP. LAN IPs are what you see when you type ipconfig in your Command Prompt and get IPv4 Address . . . . . . . . 192.168.1.101. WAN IPs are what you see when you connect to cmyip.com and get 128.120.196.204.
Just as the radio spectrum is bought out, so entire IP ranges are bought out and reserved as well by agencies and organizations, as well as port numbers. The short message is, again, that we don't have any more IPv4 addresses to spare.
What does this have to do with NAT traversal? Well, since routers were invented, direct connections (end-to-end connectivity) have been somewhat ... impossible, without a few hacks. If you have a network of 2 computers (Computer A and Computer B) both sharing the WAN IP of 128.120.196.204, to which computer does a connection go? I'm talking about an external computer (say google.com) initiating a connection to 128.120.196.204. The answer is: nobody knows, and neither does the router, which is why the router drops the connection. If Computer A initiates a connection to, say, google.com, then that's a different story. The router then remembers that Computer A with LAN IP 192.168.1.101 intiated a connection to 74.125.227.64 (google.com). As Computer A's request packet leaves the router, the router actually re-writes LAN IP 192.168.1.101 to the router's WAN IP of 128.120.196.204. So, when google.com receives Computer A's request packet, it sees the sender IP that the router re-wrote, not the LAN IP of Computer A (google.com sees 128.120.196.204 as the IP to reply to). When google.com finally replies, the packet reaches the router, the router remembers (it has a state table) that it was expecting a reply from google.com, and it appropriately forwards the packet to Computer A.
In other words, your router has no problem when you initiate the connection - your router will remember to forward the replying packet back to your computer (through that whole process described above). But, when an external server initiates a connection to you, the router can't know which computer the connection was meant for, since Computer A and Computer B both share the WAN IP of 128.120.196.204 ... unless, there's a clear rule that instructs the router to forward all packets originally going to destination port X, now to go to Computer A, destination port Y. This is known as port-forwarding. Unfortunately, if you're thinking of using port-forwarding for your networking applications, it's not practical, as your users may not understand how to enable it, and may be reluctant to enable it if they think it's a security risk. UPnP simply refers to the technology that allows you to programatically enable port-forwarding. Unfortunately, if you're thinking of using UPnP to port-forward your networking applications, it's not practical either, as UPnP is not always available, and when it is, it may not turned on by default.
So what's the solution then? The solution is to either proxy your entire traffic over your own computer (which you have carefully pre-configured to be globally reachable), or to come up with a way to beat the system. The first solution is (I believe) called TURN, and magically solves all connectivity issues at the price of providing a farm of servers with the available bandwidth. The second solution is called NAT traversal, and it's what we'll be exploring next.
Earlier, I described the process of an external server (say google.com) initiating a connection to 128.120.196.204. I said that, without the router having specific rules to understand which computer to forward google's connection request to, the router would simply drop the connection. This was a generalized scenario, and is not accurate because there are different types of NATs. (Note: A router is the actual physical device that you can drop on the floor. NAT (Network Address Translation) is a software process programmed into the router which helps save IPv4 addresses like trees). So, depending on which NAT the router employs, connection scenarios vary. A router may even combine NAT processes.
There are four types of NATs with standardized behavior: Full-Cone NATs, Restricted-Cone NATs, Port-Restricted-Cone NATs, and Symmetric NATs. Aside from these types, there can be other types of NATs with non-standardized behavior, but it's rarer.
Note: I'm not really too familiar with NATs...it seems like there are many ways of looking at routers, and information on the internet is very spread out on this topic. Classifying NATs by full, restricted, and port-restricted cones has been somewhat deprecated, says Wikipedia? There's something called static and dynamic NATs...just a bunch of various concepts that I can't reconcile together. Nevertheless, the following model worked for my own application. You can find out more about NATs by reading the links below and above and throughout this post. I can't post more about them because I don't really understand much about them.
Hoping for some network gurus to correct/add input, so that we can all learn more about this mysterious process.
To answer your question about gathering the external IP and Port of each client:
The headers of all UDP packets are structured the same with one source IP and one source port. UDP packet headers do not contain an "internal" source IP and an "external" source IP. UDP packet headers only contain one source IP. If you want to get an "internal" and "external" source IP, you need to actually send the internal source IP as part of your payload. But it doesn't sound like you need an internal source IP and port. It sounds like you only need an external IP and port, as your question stated. Which means that your solution it to simply read the source IP and port off the packet like the fields they are.
Two scenarios below (they don't really explain anything else):
LAN Communication
Computer A has a LAN IP of 192.168.1.101. Computer B has a LAN IP of 192.168.1.102. Computer A sends a packet, from port 3000, to Computer B at port 6000. The source IP on the UDP packet will be 192.168.1.101. And that will be the only IP. "External" has no context here, because the network is purely a local area network. In this example, a wide area network (like the Internet) doesn't exist. About ports though, because I'm unsure about NATs, I'm not sure if the port inscribed on the packet will be 3000. The NAT device may re-write the packet's port from 3000 to something random like 49826. Either way, you should use whatever port inscribed on the packet to reply - it's what you're supposed to use to reply. So in this example of LAN communication, you need send only one IP - the LAN IP, because that's all that matters. You don't have to worry about the port - the router takes care of that for you. When you receive the packet, you gather the only IP and port simply by reading it off the packet.
WAN Communication
Computer A has a LAN IP, again, of 192.168.1.101. Computer B has a LAN IP, again, of 192.168.1.102. Both Computer A and Computer B will share a WAN IP of 128.120.196.204. Server S is a server, a globally reachable computer on, let's say, an Amazon EC2 server, with a WAN IP of 1.1.1.1. Server S may have a LAN IP, but it's irrelevant. Computer B is irrelevant too.
Computer A sends a packet, from port 3000, to Server S. On the way out the router, the packet's source LAN IP from Computer A gets re-written to the WAN IP of the router. The router also re-writes the source port of 300 to 32981. What does Server S see, in terms of the external IP and port? Server S sees 128.120.196.204 as the IP, not 192.168.1.101, and Server S sees 32981 as the port, not 3000. Although these aren't the original IP and ports Computer A used to send the packet, these are the correct IPs and ports to reply to. When you receive the packet, you can only know the WAN IP and rewritten port. If that's what you want (you were asking for just the external IP and port), then you're set. Otherwise, if you also wanted the internal IP of the sender, you would need to have transmitted that as normal data separate from your header.
Code:
As stated above (below To answer your question about gathering the external IP), to gather the External IP and Port of each client, you simply read them off the packet. Each datagram sent always has the source IP and source port of the sender; you don't even need a fancy custom protocol because these two fields are always included - every single UDP packet must, by definition, have these two fields.
// Java language
// Buffer for receiving incoming data
byte[] inboundDatagramBuffer = new byte[1024];
DatagramPacket inboundDatagram = new DatagramPacket(inboundDatagramBuffer, inboundDatagramBuffer.length);
// Source IP address
InetAddress sourceAddress = inboundDatagram.getAddress();
// Source port
int sourcePort = inboundDatagram.getPort();
// Actually receive the datagram
socket.receive(inboundDatagram);
Because getAddress() and getPort() can return either the destination or source port, depending on what you set it to be, on the client (sending) machine, call setAddress() and setPort() to the server (receiving) machine, and on the server (receiving) machine, call setAddress() and setPort() back to the client (sending) machine. There must be a way to do this in receive(). Please elaborate if this (getAddress() and getPort() don't return the source IP and port you expect) is your actual roadblock. This is assuming the server to be a "standard" UDP server (it's not a STUN server).
Further Update:
I read your update about "how to use STUN to take the IP and port from one client and give it to the other"? A STUN server isn't designed to exchange endpoints or perform NAT traversal. A STUN server is designed to tell you your public IP, public port, and type of NAT device (whether it's a Full-Cone NAT, Restricted-Cone NAT, or Port-Restricted Cone NAT). I'd call the middleman server responsible for exchanging endpoints and performing the actual NAT traversal the "introducer". In my personal project, I don't actually need to use STUN to perform NAT traversing. My "introducer" (the middleman server that introduces clients A and B) is a standard server listening for UDP datagrams. As both clients A and B register themselves with the introducer, the introducer reads off their public IP and port and private IP (in case they're on a LAN). The public IP is read off the datagram header, like for all standard UDP datagrams. The private IP is written as part of the datagram payload, and the introducer just reads it as part of the payload. So, about STUN's usefulness, you don't need to rely on STUN to get the public IP and public port of each of your clients - any connected socket can tell you this. I'd say STUN is useful only for determining what type of NAT device your client is under so that you know whether to perform NAT traversal (if the NAT device type is Full-Cone, Restricted, or Port-Restricted), or to perform all-out TURN traffic proxying (if the NAT device type is Symmetric).
Please elaborate on your roadblock: if you want advice on best practices for designing an application messaging protocol, and advice on reading the fields off received messages in an orderly and systematic fashion (based on the comment you posted below), could you share your current method?
Your question is really broad - I can't offer an example but the following links might help (specs, libraries, samples etc.):
http://java.net/projects/stun
http://code.google.com/p/ice4j/
http://jstun.javawi.de/ and http://www.t-king.de/blog/index.php?category=JSTUN (BTW: JSTUN is no longer maintained from what I gather)
https://www.rfc-editor.org/rfc/rfc5766
http://www.codeproject.com/Articles/23481/Stunner-A-STUN-Library-and-Client (is in C++ but might illustrate how to make it work)
STUN basically works as follows: your client behind the firewall connects to a STUN server outside the firewall. The STUN server inspects the packet received from the client and sends the client a response back containing the clients IP and port as they appear to the STUN server.
This is how the client behind the firewall discovers its own external IP and port. As far as I know a STUN server does not normally pass address information from one client to another.
Typically STUN is used to set up media streams through firewalls, when the firewall is already open to signalling traffic - e.g. in VoIP: client contacts a STUN server to discover its own external IP and port for UDP traffic, it then sends its signalling request (SIP INVITE or whatever) to the other client on a well-known open port - including its external UDP address info in the payload (SDP or whatever). So generally one client needs to be reachable over an open port for signalling for peer-to-peer communication.
Your issue is not a Java related. If you know how to open a UDP connection, that is enough. Read the content of the following link. Don't be scared by the title, it also covers UDP. The rest is just Java coding.
P.S.: In your scenario, there is a missing step. Both A and B must have an open connection to S, because S needs to tell B that A is trying to reach it. If B does not have an open connection to S, there is no way A and B can start communicating together.
UPDATE
The answer made by Jason contains errors and wild speculation about NAT traversal. One should read the work done by Saikat Guha (mpi-sws.org/~francis/imc05-tcpnat.pdf) to really understand this matter. The cone classification of Wikipedia is completely obsolete and misleading.

Pinging computers on a network

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.

Categories

Resources