Connect to a client that has dynamic IP address - java

I'm working on a server-client project. I hosted server on Google app engine so there is no problem with IP there, all the clients can connect to the server easily. Yet the problem occurs when I try to connect to a client, which is quite complex because I don't have static IP for the clients. Can anyone suggest me a good way for server-client coomucication in this case, without requiring that clients must have static IP address?
Thank you very much.

Well, obviously the client should register itself with the server and update it's IP when it changes.
There is, for example, a program which does exactly that and then publishes the IP with a DNS.
But you should be aware that the IPv4 address space is not that big and a lot of internet clients do not own an IP (and work thru the ISP's NAT). If you have clients that do not own an IP then you might want to stick to the usual Pull: the clients should periodically issue a request to the server to check if there are new messages for them. With a Keep-Alive connection and an efficient server implementation the price of such checks might actually be low, although that kind of communication might not work very well with the GAE pricing.

Related

How to efficiently network an application in Java

I was wondering if someone could give me a clue. The situation is we have one computer that has a server application, the rest have a client application. Now my question is how would i keep track of the server ip address? What I want is have the clients automatically hunt the server application, regardless of the ip address and find it, because using a wireless network computers are using DHCP. So I was wondering is there anything that can be buried in a computer using Java with which other computers can identify the application. Thanks.
The "good" way is to use DNS (imho the ONLY solution in a productive environment), as #Peter Lawrey already mentioned, and i would prefer that solution.
You have two other possibilities:
Let the server broadcast his address on the network.
Let the clients scan the network.
Both this solutions are not ideal, because you create a lot of noise on the network, may be blocked by a firewall, etc. Therefore, i really suggest you to use DNS.
If you can not use the DNS solution i would go with a solution that lets the clients search for the server.
Take a look at this SO question, might get you started.
If they're on the same physical network, your server can broadcast its IP address via UDP to the broadcast address for that sub net.
You could even follow the uPnP standard.
Alternatively, you could host the location of the server from a known other location, like a web server. For example, call an action on the known web server to retrieve the IP address of the server. This allows you to utilize DNS to look up the first host, then go from there.
If you know the DNS-Name of the server you can use that name instead of the IP. Java takes care of the DNS lookup.
Otherwise, I guess the simplest solution is just to scan the IP range of your network and just try to connect to each IP and test if it works.
Other solutions would include broadcasts by the server and would be much more complicated and maybe overkill for a application hosted in a small network.

How do I create a network connection with other computers (JAVA)?

I'm developing a game that can be played with computer or versus other players. The GUI is Swing but irrelevant for the matter. My question is : how do I connect with other players in a network?
I am familiar with terms like client / server, sockets etc, and i can write a basic client/server program, but it can only be run from ONE computer. I don't know how to connect to this network from a computer, say, half way across the country.
You are probably setting behind a router which hides your local IP address from the rest of the world (look for NAT for more info on this). Basically, the world only sees your YOUR_ROUTER_IP, your router takes care of carrying all IP packets from the outside world to you and vice versa. You will need to change your router settings so that your computer/server gets the router ip address. This way you can access your server application from anywhere in the world by using simple socket operations.
I hope this helps.
I like to use Kryonet for network connections, it works very well and has really good documentation.
You indicated you know how to use client and server sockets, so I'll just throw out there that you ought to try connecting with "real" ip address instead of localhost (127.0.0.1). Take two machines on your local network, get the IP address of the "server" machine and use that address to connect from the client.
This will work all the way around the world, except for the fact that you are likely behind some Network Address Translation (NAT) firewalls and will likely need to "open" or "forward" the ports you need. If you need more information on NAT, google and serverfault will be pretty helpful.
If your client and server is located on the same machine, then you can use loopback address(ie 127.0.0.1), in LAN you can do with private ip addresses
Private ip address for LAN
CLASS A - 10.x.x.x
CLASS B - 172.16.0.0 - 172.31.255.255
CLASS C - 192.168.0.0 - 192.168.255.255
you can use this for LAN environment
For connecting someone over the internet, you will need Public ip addresses.
Address apart from the private ip in every range are public address.
Now if you have a server which is having a static ip then it wont be a problem for the client to access it anywhere from the world over internet.
But if its over a LAN , and accessing the internet from a gateway, then there will be a NAT, then you will need to set the inbound and outbound traffic rules at the gateway, for letting the client access the server.

How do I send data between two computers over the internet

I have been struggling with this for the entire day now, I hope somebody can help me with this.
My problem is fairly simple: I wish to transfer data (mostly simple commands) from one PC to another over the internet.
I have been able to achieve this using sockets in Java when both computers are connected to my home router. I then connected both computers to the internet using two different mobile phones and attempted to transmit the data again. I used the mobile phones as this provides a direct route to the internet and if I use my router I have to set up port forwarding, at least, that is how I understand it.
I think the problem lies in the method that I set up the client socket. I used:
Socket kkSocket = new Socket(ipAddress, 3333);
where ipAddress is the IP address of the computer running the server. I got the IP address by right-clicking on the connection, status, support. Is that the correct IP address to use or where can I obtain the address of the server? Also, is it possible to get a fixed name for my computer that I can use instead of entering the IP address, as this changes every time I connect to the internet using my mobile phone?
Alternatively, are there better methods to solving my problem such as using http, and if so, where can I find more information about this?
EDIT:
Would it be possible to have the server program running on a server on the internet somewhere. My original server would then be a client that send information to this server. This server would then pass this information to my original client and vice versa. That way, the IP address of my computer won't matter, as I only need to know the address of the server hosted somewhere on the web. Does this seem like a better solution? Where do I begin implementing such a solution?
Thanks!
When you connected to the server that serves StackOverflow, did you type in the IP address? It's 64.34.119.12, if that jogs your memory.
You probably didn't. You probably typed "stackoverflow.com". There's a huge, complex, clever, and in some ways, poorly implemented system called DNS that translates sensible and human-readable names into IP addresses.
One problem with DNS, though, is you need a "static IP", which is exactly what it sounds like: an IP address that doesn't change, which is exactly what you don't have.
So, what can you do?
You can buy a static IP account from your ISP (pretty expensive)
You can use some proxy out in the Internet (a machine that does have a static IP and is willing to bounce your packets back and forth -- I'm not aware of any service that does this for you; you could write one and put it up on Amazon Web Services or Google App Engine, both of which would be free at your level of usage, but they'd be slow, since every packet trying to cross your living room would have have to go via some data-center in Virginia).
You can keep doing what you're doing, looking in the net-configuration of your machine.
You could speed (3) up a little by having your server program look up its own IP address and print it out where you could see it and type it into the server by hand.
You can use DynDNS, as Sergey mentioned (this is the "right" solution, in that it's very general, it just might be a little complicated to set up)
You can use multi-casting.
Multi-casting is an interesting solution, and it may work for you. The idea is, when your server starts up, it announces to the net, "Here I am, I'm providing X server, here's my IP address, talk to me." The problem is, a multi-cast won't leave your living room. Obviously, if every multi-cast were spread to every computer on the Internet, the whole thing would collapse, so your router will ignore, and not route, multi-cast packets. That may or may not be a deal-breaker for you. EDIT Re-reading your question, I see it is a deal-breaker for you. I'd go with #5, but be aware there may be routing issues (address translations that prevent a server from knowing the address that other computers can find it at) or fire-wall issues (that is, your ISP may prevent your server from receiving incoming packets even if the address is correct).
using a direct socket connection with a port like 3333 is usually complicated because different network configurations.
firewalls will make a pleasure preventing the connection, or killing it from time to time.
maintaining a 2-way connection can be a nighmare. the SIP protocol is struggling with this kind of problems.
For a simple application, i suggest you look into the comet technology, where your clients can establish an http connection with a shared server. The server can then bridge commands between them.
html5 will also bring the websocket protocol to the table.
I got the IP address by right-clicking
on the connection, status, support.
Not sure about the "support" part, and I'm not on a Windows machine right now, but I think that the most easy and reliable way to figure out the IP address on Windows is to run "ipconfig" from the command line (Win+R, type "cmd", then "ipconfig" in the opened window). This, of course, should be done on the server side.
However, the problem is that depending on the ISP your IP address may be not within the Internet, but within a local ISP network (so-called NAT). In this case, you'll need to use some sort of black magic called TCP hole punching, which is very complicated and not guaranteed to work. You can figure out if your address is local or not by looking at it. For IPv4 local addresses are almost always like 10.x.x.x or 172.16-31.x.x, or 192.168.x.x. Don't know about IPv6.
You can also check your IP by visiting one of the special sites like www.whatismyip.com. If the address they tell you is different from the one you see by running "ipconfig" or looking at the connection properties, then you're almost certainly behind a NAT (or your ISP is using a transparent proxy, but that's rare).
If you are directly connected to Internet (no local addresses and NAT), then you should also check if you have any firewall software and either to configure it to allow connections to the port you use, or make sure it's in "ask the user" (and not "silently reject") mode, or just disable it completely (this may put your computer at risk, especially if there is no anti-virus software or the system isn't up-to-date).
Also, is it possible to get a fixed
name for my computer that I can use
instead of entering the IP address, as
this changes every time I connect to
the internet using my mobile phone?
Yes, it's possible. There is the thing called DynDNS, and there are DynDNS providers like DynDNS.com, where you can get a third-level domain name for free (like mycoolpc.dyndns.org). You'll have to install and configure some DynDNS client on your PC that will tell the DynDNS server its new IP each time each changed. I don't know anything about particular clients to use because I'm using the one built-in in my home router.
No need to write networking code for this, unless it really floats your boat. Take a look at SCP. http://amath.colorado.edu/computing/software/man/scp.html. There is a windows implementation where you can download putty (windows ssh client), and it is on most linux distributions. Alternatively, you could set up an FTP or SSH server on one or both of the machines.
"a fixed name for my computer that I can use instead of entering the IP address" would be a domain name, these are purchasable online for a few bucks.

Discovering clients on a wifi network

I'm writting a java application, and I need to quickly discover any other running clients on any wired or wireless local networks in order to establish a TCP connection.
what's the best way of doing this? Are there libraries or code snippets that would do this?
Multicast UDP is a good way of doing this. It's used in a couple of technologies that support automatic discovery of networked devices over local IP networks (UPnP and ZeroConf).
Multicast UDP is not TCP, but it is still based on IP and, so, uses the same addressing mechanism i.e. IP addresses. Quite often it is compared to radio broadcasting i.e. a multicast sender only needs to send 1 message (i.e. it is like a broadcast) but only clients that are "tuned-in" to the multicast channel will receive it.
You can do a quick search on google or wikipedia for these as a starter, but the basic idea is as follows:
when a client starts, it sends out a multicast UDP "hello" message to some pre-specified multicast address and port (e.g. UPnP uses 239.255.255.250:1900)
existing clients are listening for incoming multicast "hello" messages on the specified address and port - when a client receives one, it sends a response to the sender
the client sending the "hello" message receives a response from each existing client on the network and is now aware of the IP address of each client
If you are looking for libraries to use, UPnP libraries can tend to be a bit heavyweight and a lot of folk generally don't like them, so ZeroConf might be a little more suitable. I don't know of any java implementations of such things but I'm sure you can find some with a little digging around.
A network scan can be very long, even longer on wireless networks. If you need them quickly thru Java you may implement a "meeting point" server on your network. This server listen to a predefined port, clients register on the server on startup and the server can distribute information about the clients on request.
HTH.
I guess you need to do a scan on your application's port on all IPs in your subnet.
Just what are the available IPs - or what is your subnet for that matter?
I'm afraid determining that could turn out to be impossible as the network is designed to be transparent to your application.
So, i'd use brute force: pick your IP and change the last byte. Might be too much, might be not enough though.
Or you send a broadcast (which usually would be targeted at x.x.x.255) and see who answers.
See Datagram Broadcasting and Multicasts. But i think that's not TCP/IP anymore.
There is a JGroups toolkit for reliable multicast communications. It allows automatic discovery of additional clients using Multicast techniques as described in other answers.
It also provides communication APIs on top of multicast sockets.
It is used in a number of projects such as JBoss, Tomcat and more to provide an infrastructure for distributed cache. See more here.

Java Sockets time-out over the Internet

I created a small chat program, that works flawlessly when client & server are run on the same computer (and probably network, too).
However, as soon as I try to connect to another computer over the internet, the socket connection simply times out.
Is this because of firewalls / routers, etc?
And how can I connect a ServerSocket & Socket over the internet?
However, as soon as I try to connect to another computer over the internet, the socket connection simply times out. Is this because of firewalls / routers, etc?
Yes, most likely. You're running into the NAT problem: essentially, the same externally visible IP address maps to many internally visible endpoints, and external endpoint doesn't know which internal endpoint to give your socket request to.
The easiest way around this is to have both your clients connect to a third party which both of them can see, and then have the third party mediate the communication. This is how most instant-messaging protocols work, for example.
If you have no way to control a third-party entity like that, an alternative to directly connect two clients is to have both clients open up an agreed-upon port, and then map communications on that port to their own internal endpoint. This provides the missing link that the externally visible endpoint (e.g. your home router) needs to deliver the communication to its intended destination.
If your server is behind a NAT router box (and most home computers are, especially if you use WiFi), then it won't be reachable from the outside unless you set up your router to port forward to that server.
What's the IP of your server computer? If it's 192.168.x.x or 10.x.x.x, then it's a non-routable address and can't be reached from outside.
Assuming with running on the same computer you mean that you tell the client the server is at 127.0.0.1 / localhost, it shouldn't be a problem in your code but because of firewalls or routers. If your server is behind a router performing masquerading (i.e., the server doesn't have a public but private IP address like 192.168.x.y for instance), you have to configure the router to pass a connection from the internet to the computer running the server.
Another reason why it doesn't work might be the way you bind your server to the interface. If you specify 127.0.0.1 there, the server will only listen for requests coming from the same system. If you don't specify an address, it will listen on all interfaces.
Edit Your comment indicates that you indeed have the NAT problem like others said. Configuring your router accordingly is probably the easiest solution.
First, test to see if it really works on a LAN; it sounds like you're just assuming it does.
If it works on your local network, perhaps it's failing because the server lacks a public IP, and is running behind a NAT'ing router.

Categories