Skip to main content
GameDev.net gamedev.net
🔒 Locked

Follow-up question to the FAQ9: NAT Punch-through

Started by Christian Schlager Nov 6, 2007 at 8:04 AM 4 replies 1.5k views
Original Post
Christian Schlager
Christian Schlager
Hi, I created a simple game for two players using Winsock. However, both me and my tester sit behind routers. I've read up on NAT, Punch-Through and introducer systems. However, do I really need all that? I could get my proper IP address, as in Q18 suggested, by bouncing a query off a public server (by the way, does that mean any server, such as gamedev.net?). After that I could just give that IP to my friend via ICQ. Will he be able then to join the game I am hosting? Or am I missing something? Thanks in advance for your help :)
ToohrVyk
ToohrVyk
Your computer has a local IP address, as provided by your router. For instance, 192.168.0.2. Of course, giving this address to your friend will not work unless he's on the same router as you. Your computer has no global, internet-visible IP address. Instead, your router has one. For instance, 129.199.192.1.

When you connect to a website, for instance 72.14.207.99, what happens is that a connection opens between a random port on your IP and the port 80 on 72.14.207.99 (for other types of connections, the server port varies). This is the ideal case without a router, when both client and server are on the same network.

If they aren't, the router plays a man-in-the-middle role: a connection opens between your computer and a port on the inside (local) part of the router, and simultaneously a connection opens between a random outside (internet) port of the router and the port 80 on 72.14.207.99. So, you have a connection between 192.168.0.2:XXX and 192.168.0.0:YYY, and another between 129.199.192.1:ZZZ and 72.14.207.99:80. The router merely forwards the data from one side to another.

All servers on the internet would see your router's IP, not your computer's (and your computer IP is local and thus worthless). In short, the entire problem with routers is that external computers can only contact your router.

So, your friend connects to your router, on the correct port for your game, and your router just doesn't know which local IP it should forward the connection to. This is the problem with routers: inside-to-outside connections work because the router knows which local IP is the requester and which remote IP is the requestee, but outside-to-inside connections don't work because there's no local IP information available.

The solutions involve having the player behind the router start up the connection (the point being that it's an inside-to-outside connection), which is what the bottom line of NAT punch-through is about, or setting up port forwarding on your router (which tells your router, "when someone contacts you on 129.199.192.1:XXX, he's actually looking for 192.168.0.2:XXX"). The result will be that people connecting to a server behind a router hit the router, which forwards the connection to the actual server.
hplus0603
hplus0603
Getting your public IP address will work if you set up port forwarding from your router. It says as much in the FAQ, if you keep reading. To get your public IP address, try a server such as www.whatismyip.com

enum Bool { True, False, FileNotFound };
Christian Schlager
Christian Schlager
Thanks for your replies :)

Can I choose a random port, say 8000? I mean, from that range of allowed ports?
In my two-player game, do we both have to have port forwarding set up or only the host?

edit:
I tried hosting a game with setting up a port forward on port 8000 and in the settings dialog of my router selected my computer. When joining my friend uses the IP I got from whatismyip.com and port 8000. But it doesnt seem to be working :(

[Edited by - Christian Schlager on November 6, 2007 5:41:15 PM]
hplus0603
hplus0603
Only the server needs to port forward, if your application is NAT clean (which means it either uses TCP established from client-server, or uses UDP and responds with sendto() to the same address it gets in recvfrom()).

Did you call htons() on the value 8000 before you passed it to bind()?

In general, use Wireshark to debug networking problems on the wire.
enum Bool { True, False, FileNotFound };
Christian Schlager
Christian Schlager
I am using C# and XNA and the equivalent seems to be IPAddress.HostToNetworkOrder(8000).
But no, I havent. Using it causes my spritefont-output-thingy to crash with the weirdest of error messages:
The character 'ß' (0x00df) is not available in this SpriteFont. If applicable, adjust the font's start and end CharacterRegions to include this character.
Parametername: character

Consequently I cant see what exception it throws..yet. Once I figure that out I'll have some more questions. Promise!

edit:
Thats the line:
Listener.Bind(new IPEndPoint(aryLocalAddr[0], IPAddress.HostToNetworkOrder(8000)));

It's an ArgumentOutOfRange Exception..oh wait, the constructor info says port argument is given in host order, so I guess I dont need to call it. I am back to square one :(

2nd edit:
got it...YAY!
how embarassing, I didnt read the faq answer as careful as I should have..
I opened the port in the router and thought I was done, but I didnt open it in the XP firewall...

[Edited by - Christian Schlager on November 8, 2007 4:43:14 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.