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
The problem: In java you can create a socket on the server with ServerSocket(0) and it will choose a random port to listen on. However when you create a socket on the client to send a message with Socket(addr, port) there is no apparent way to determine which port on the server you need to send to. I couldn't find anything about this option through web searches besides the basic "if you put 0 it will chose a random port". Does anyone know or have a resource that could explain what this scenario is supposed to look like from the client end?
Some background: I am currently converting a system from UDP to TCP. The reason I need the server to listen on a random port is that my server/client do not have a strict server/client relationship. So the "server" in this situation is really an application that I need to open multiple instances of on one PC. The old way of having predetermined send/receive ports is causing only one instance to be able to open a port and all communication is being redirected to that instance. My understanding that the best way to fix this problem is for each instance to use a different port, and the best way for that is to do ServerSocket(0). Despite including this background, I do not want comments on how messed up the situation is, only answers pertaining to the problem.
If a fixed port number is not part of the server's documented setup / protocol, then the only way for clients to figure out is to have the running/active servers publish that information in some datastore, the location and details of which are documented and known by the clients, and where that datastore is reachable for the clients.
[Or have the clients run a portscan each time they want to connect. It will work but probably not as fast as your users would like.]
And your situation is indeed messed up.
Perhaps if you are on the same IP subnet with all the servers/clients, then you could use UPnP to signal which random port new instances of your application are running on, and similarly other instances could monitor UPnP to discover this new instance.
I've never implemented UPnP in Java, but suspect libraries are out there..
eg. https://github.com/jupnp/jupnp
I am doing an android app allowing users to play online.
Currently, I use a TCP server: when two persons are connected, the server takes care of forwarding the packets between the two clients.
I would like to replace my server by a java servlet with google app engine. This new server will just be used to connect the two players.
It would work in that way:
Player A opens a server socket and then post to the server the connection details.
When a player B wants to play against A, he asks to the server the port number of A and he connects directly to A.
The problem is that I am not sure that it will work if player A is behind a NAT. When player A opens a server socket, that opens one port of its 192.168.x.y address, but does it ask to the box a port forwarding? I assume it doesn't...
So two questions:
Is it possible to make a direct connection TCP between two devices even when there is a NAT or a firewall (I don't know how firewalls work on Android...)
If it isn't possible, what is the best solution: Is it possible to make a TCP server to ensure the exchange of the messages with app engine?
Thank you by advance.
game
Creating direct TCP connection between users under different NAT is mostly possible. There are 4 types of NAT. FC, ARC, PRC, Symmetric. If one of player A or B has symmetric NAT then it is impossible to create TCP P2P connection. In this case you will have to use a server in the middle for exchanging data between two players.
For other types of NAT combinations it is very much possible but not guaranteed. The technique that is used to create TCP P2P connection is called TCP hole punching. Read this answer to know in details about this technique.
Also creating TCP P2P connection is not related to any platform.
First, the device itself is probably not going to be the main problem. If they are at home and using WiFi, you will probably have to deal with a cable modem/DSL modem, which typically includes a firewall. Also if they are at work (or a hotel, conference center, etc.), there may be a corporate firewall to deal with.
I believe most home cable/DSL modems support uPnP (Universal Plug and Play), which includes the Internet Gateway Device Protocol (IGD) designed to let devices determine the external IP address and set up port mappings. In general you can look up NAT traversal for ways to handle connections through a home modem/firewall. I will note that corporate firewalls are a different matter and many of these techniques won't work.
So probably I would recommend you be ready for at least the following four scenarios
Direct connection with nothing creating problems. You can test this by having the server do a test connection when the player first contacts the server. If this works, things are simple.
Home NAT device that understands uPnP. If you have a 10.x.x.x, 172.16.x.x-172.31.x.x, or 192.168.x.x number (typical home WiFi), then you can try to set up the NAT traversal and if that works you can send the appropriate information to your server. It probably would be worthwhile for the server to do a test connection just to be sure that things work.
If you have a firewall that you can't get around, then make a note on the server regarding player A, and when B tries to join A's game, look and see if B will accept connections, and if so then arrange for A to connect to B instead.
If none of the above work, then have A and B both connect to the server and have the server relay messages between A and B.
If you don't want to program all those possibilities, then option 4 is the one that is most likely to work, even if it does mean extra traffic going to/from your server. But note that for corporate networks, they may simply have a rule blocking unknown connections, and there may not be much you can do.
Edit: I was able to get a simple TCP server working on Android without anything special regarding Android itself, so removed a comment saying I didn't know about that.
Thanks for any answers in advance.
Anyways, I made an android application, (This isn't an android question), and it connects to your computer so you can monitor it. Well I have the server for the computer ready to the client from the phone can access it, it works perfectly. The problem is, You have to port forward, and not everybody knows how to do that. Is there a way so you can programmatically make it so you do not have to port forward?
Thanks again!
You mean you had to set up port forwarding on your router (because you're using a router with your broadband connection)?
No.
You would need to set up a intermediary server on the internet somewhere that both could connect to, then forward the data through that.
You can have both connect to a server of yours. More of a pain than any other method, but guaranteed to work.
I'm not sure about the specifics of the droid, but you may be able to access the droid directly through its IP.
Otherwise you could set up a simple tutorial program, with specific instructions on how to port forward. You could even make a little program to access certain popular vendors port forwarding directly. Maybe just a little thing that asks for a password and connects and does everything automatically. Wouldn't be horribly difficult with some vendors.
I created a game and I want to put it on online. I want to buy a website (I'll probably use goddaddy to buy a domain name and use them as the web host) to use as the server to handle game play. Because I would need a separate server for each game, I would need each game's server to exists on different ports. So this leads to my question, is is possible to access these ports on my future web server? (I wrote the program in Java, so I would assume that I would access the ports from the server side by choosing a port for a ServerSocket, and from the client side by using the IP address from the website and the chosen port for a Socket)
(note: also, I am aware that it may be easier to simply use one port and run the servers on different threads instead, but I am just curious to have my question answered)
thanks a lot,
Ian
Technically it is possible to use different ports, but I don't think that a webhoster like goddaddy will let you run a java process that binds to a special port.
If you mean that you are going to create your own TCP server you obviously can create as many instances of your server and configure them to listen to different ports. But it is year 2011 now. This solution was OK in early 90s.
I'd suggest you to use Restful API that works over HTTP. In this case you can forward calls to server side of each application using URL, e.g.
http://www.lan.com/foo/login?user=u123&password=123456 - log in into application foo
http://www.lan.com/bar/login?user=u123&password=123456 - log in into application bar
In this case you need only one server (the web server) that is listening to socket (port 80).
Your server side implementation could be done using various web techonlogis (php, java, asp.net etc) on your choice.
Yes, that should work. The security manager permits connections to a different port on the same IP address that the applet was loaded from.
You can run a Java server on whatever port you want. Each server will accept incoming requests on one port.
The correct way is simply run on one port and each connection will instantiate a new servlet instance (which happens to run in its own thread) that can then service that request. You usually don't need to run separate ports or worry about concurrency, especially if all the stuff that's shared between connections (e.g. multiple players in one game) is handled through database read/writes.
Your host (GoDaddy) will have to allow you use of those ports, but if they are providing proper hosting (not virtual hosting) and given you your own IP there's no reason why you shouldn't be able to.
Your solution may work theoritically, and I like AlexR's solution. But providers like godaddy doesnt let you run a java server, on ANY port. You will need to find out somebody who does. What I found is the cost goes up from $5/mo to about $20/mo, but you get a much better (read faster) machine. Good wishes, - MS.
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.