I made a networked game in Java using Sockets. It works great, except... only through my LAN. :/ What I want to be able to do is set it up so that I can start the server running on my home computer and send the client code, in an executable jar, to someone else, and have them be able to launch it and connect through the internet. But like... I have no idea how to set up my modem & router for that. :( I have a wireless Clear modem, for which the configuration page looks like this:
http://imageshack.us/photo/my-images/254/modem.jpg
And a Netgear router, whose page looks like this:
http://imageshack.us/photo/my-images/443/routerq.jpg
Right now, in the client and server runner classes, I pass my PC's private IP address along with my chosen port number to the ServerSocket and Socket objects. I hear that Sockets are able to be either UDP or TCP, depending on how you set them up, or something...? I don't do anything like that though, I just instantiate them and pass them the 2 values, and off they go...
In the code for the server:
ServerSocket sock = new ServerSocket();
sock.bind(new InetSocketAddress(IP, 9001));
Code for the client:
Socket sock = new Socket(IP, 9001);
So also, I would need to know how to change the code accordingly with the changes to my router/modem settings.
"IP" is a String representing my computer's private IP, 192.168.1.10, and the program only works if that is the string I pass to the Socket & ServerSocket. Like I said, I have a modem which is connected to a router which is connected to my computer. So, can someone please explain to me (in detail, because I'm a noob) what exactly I would have to do to configure both of them, AND the changes I would have to make to my code?
You'll have to manually port forward, or look at a solution like UPnP or NAT-PMP for automatic port forwarding. Unfortunately, NAT is a pain in the ass to configure and most routers don't properly support it. It's also not a simple task, as you have to support a whole range of different implementations and mechanisms.
It shouldn't be too difficult to set up your router to forward one port to your machine, though. See http://portforward.com/ for an awesome list of how to do it on pretty much any router.
It sounds like you're asking a number of questions here... I'm no network/socket programming specialist, but here's some ideas.
For distribution, you may wish to look into Java Web Start. It'll make it easy for your clients to obtain the app as well as automating updates.
If you're using the Socket constructor like that, the actual implementation will be a system default. You could override this by calling this method with a suitable SocketImplFactory implementation.
As for the IP address and port... Using a hard-coded value for the port should be okay. You'll need to decide on a port or at least some default anyway for clients to connect to. Even so, it might be useful to have the value read from some external configuration file. This'll make it easier should you ever decide to distribute the server app to let other people run servers. They might want to use a different port.
Having the server's IP address (yours) hard-coded in code is definitely a no-no, though. Clients should connect using either an IP address or host name that they need to provide or set in some configuration file. A host name would be required if you don't have a static IP address.
Unless this is something for you and some friends to enjoy, where you can always just initiate a game by providing IP and port in a chat session or something, you'd be better off finding some external hosting solution at a company that takes care of the DNS resolution and network setup for you. These days you'll find stuff like that pretty cheap if you don't have requirements like a Java EE server or database.
EDIT: thought of something else. TCP might be okay for your use-case, but if this is a game that requires minimal lag and quick input synchronization (like a shooter or fighting game) then it's not the best choice. In that case UDP would be better. It would induce the requirement of adding some sort of detection for desync or a mechanism that makes up for any dropped packets.
Related
Heyy guys. I'm writing a chat application in java, works pretty well. But can i somehow host my Server file or the Serversocket on the web? I want to make it so my friends from other pcs can use the client and connect to the server file which is hosted on the web. Is that possible? Can i host the File/socket online?
When you run a java application that opens a ServerSocket, it opens a port on your local machine and starts listening for incoming connections. What you do with those connections is up to the implementation of the java code that you write.
The "web" is much less foreign than you are making it out to be. Your own computer can be on the web that you're talking about and people can connect to your chat service. Or you can choose to host it on something like an AWS server.
The following approach is assuming you are behind a pretty standard NAT config.
Once you run your java application, you need to make sure other computers can see you, either inside your LAN or outside on the internet. You want to start testing from as close to your computer as possible, then start expanding outward.
First you need to make sure that your computer's firewall is actually allowing connections on the port that your java application is listening on.
Opening ports in the Windows Firewall
Setting up and opening ports in Linux
Now computers on your LAN will be able to connect to your java program. Now you need to go one layer out, and port forward your router. This is much less standard so I can't help you too much, but Google can.
At this point, anyone on this internet, knowing your external ip and what port your java application is listening, can connect to your service.
If you chose to host this on an third party hosting service, you'll need to go through similar steps, but there may be slight differences that you can either ask about, or again Google is a great resource.
I'm wondering if there is a way to setup connection between a client and a server over the internet and have both of them programmatic setup all needed router/firewall configuration changes to open needed external ports to communicate.
Assuming both server and client have known ip addresses and a DNS is not needed in this example to find the IP addresses. How might one have a server that when started configures access past the firewall and tells the router how to route proper communication to the server. I would assume the client may not need anything like this as it should only need to know the external IP address and port number of the server. If i'm wrong about my assumption please let me know.
Example if I have two houses house (A) has a server and house (B) has a client and both sites know what the other house external IP address is and know what port they will be using how may a Java application do all the configuration or at least do as much as possible on say windows,mac,ubuntu. The idea is the user of the server and client should not have to do a bunch of firewall/router configurations to get the application running. It would also be nice if in the example it shows how to release the connections when the server is terminated. Example when the java server is turned off it should close up port settings on the firewall and router. security and clean house.
There is no easy way of doing that as it will depend on the OS and on the many possible firewall application running on the machine. Plus, if your app crash, you will never set back the original parameters, which can be problematic when talking about security. Instead of trying to set up custom configuration, you should try to use standard communication template/protocol like http. This will gives you a high probability of your app running without additional configuration almost anywhere (since there is almost no point of having an internet connection if you don't allow http port).
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.
What I mean is like servers on video games. You can run an application and it will set up a server on your computer with an IP and a port.
For example, how would you make an application where one host application sets up a thing where it has an IP and a port, and another computer that has access to the internet as well can type in the IP and port and it would be able to communicate with the host? I mean simple communication, like sending a boolean or String.
And would there be any security problems that would be needed to fix?
I guess I grasp the concept of your question...
You want two computers to connect via internet right? If that is the case, then you will have to use a thing called "sockets" that do connections between computers. About the server thing, well, for starters the client must always know what IP the server as (direct IP or by a DNS), and then you can connect your client to your server. There is a tutorial for sockets at the java pages: http://download.oracle.com/javase/tutorial/networking/sockets . About security issues, well, you must make sure that your server can handle anything that comes from the client (i really mean everything), i mean, accepting every type of data that is supposed to receive and deny everything that is not (trash per say). If you have that in mind then there is no problem (and of course, the server must have a firewall also to control the sockets, but that's not up to you).
Here is an example of how to use sockets to send a string from a server to a client.
http://www.java2s.com/Code/Java/Network-Protocol/StringbasedcommunicationbetweenSocket.htm
The site has about 20 examples of how to do what you are trying to do. In general I find this site to be the best JAVA resource that I know.
In general, the thing you probably want is a Socket. Sockets allow you to send bytes to an endpoint via TCP or UDP. This is very low-level, though, and are somewhat tricky because you have to design your own application protocol. You may want to use something that offers more abstraction.
Java sockets expose a stream interface so you could just encode integers as strings, for instance, and send them line by line, or you could do something fancier and more efficient like using a DataOutputStream to wrap it.
Handling the following issues can improve security.
If you have router ,set different ports for routing.
Example: If you are running server say on port 6001, map a virtual port say 9001 , which would be exposed to public.
DDos
IP Restriction - Not every user can access your machine !
Enabling router firewall does handle most of the issues.
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