It depends on whether there is any Network Address Translation (NAT) going on. Most corporate nets use this to save on the number of public IP addresses they need. Cable & DSL routers for connecting multiple home computers to a single broadband connection also use it.
NAT exposes only a single IP address to the internet. You may wonder what happens if more then one computer behind the NAT-router puts out a request from the same port to a server on the internet. How does the remote server send data back and ensure it is routed to the correct computer behind the router? This is achieved by a process called port mapping. When a computer sends a packet out through the NAT router, the senders IP address is replaced with that of the NAT router. The senders port number is replaced with an unused port number on the NAT router. The router places this mapping in a table and will maintain it in that table for an unspecified but large number of minutes. Meanwhile the packet goes to the server, which processes it & then sends it back to the exact IP:port that it came from. The NAT-router receives it, looks up the mapping in it’s routing table and replaced the ‘to’ IP:port combo with that from the table. It can then forward the packet to the computer than originally sent the request.
That is how an HTTP request originating behind a NAT router gets to a webserver & how the reply gets back to the sending computer. Note that it is only the webserver that receives requests on port 80. The client uses any port above 1024 for the outgoing request & this in turn is modified by the router.
The key thing about this protocol is that for data to get from the internet to a particular computer behind the NAT-router, there must be an entry in the routing table. An entry can only get there if:
i) The interchange was initiated by the client (as discussed above)
ii) The user has manually made a permanent entry in the table. This is called port forwarding.
iii) The application running on the client makes an entry in the routing table. This uses Universal Plug and Play (UPnP)
This means that if you have two clients, each behind a NAT-router then they cannot directly initiate communications. This is why a NAT-router functions as a basic firewall. It protects the computers behind it from unsolicited connections. However this really breaks the peer-peer (client to client) communication model. There are four basic solutions:
i) You can run all communication through a server which isn’t behind a NAT router (or if it is, use port forwarding to force an entry in the routing table). For turn based games, you could run this on a webserver using PHP & mySQL, clients would have to poll the server regularly (say once a second) to see if it was their turn yet. A dedicated server would allow custom server software which could maintain a continuous connection, which is more flexible, but costs more. NB. Real time games need a higher polling rate, which means the PHP/mySQL combo is not a realistic option. You might also look at java servlets. These are mostly used as a backend to serving webpages, but you might be able to do more with them. Cost is more than PHP, but less than a dedicated server.
ii) You can run peer-peer using UDP packets (TCP doesn’t work with this) by implementing a simple server which just keeps a list of IP addresses, port numbers for each client & sends the list to any other client that requests it. This is called UDP punchthrough. The key thing with this simple server (called an Introducer) is that it must also listen using UDP. Thus you cannot use a normal webserver to run this service. That potentially puts the cost up of the implementation as you need a dedicated server.
iii) The client uses UPnP to automatically configure the NAT-router to do port forwarding. However this is a very complex protocol to implement and most routers have it switched off anyway as it is a security risk. If a virus got onto your computer, it could use uPnP to open a port on your NAT-router to allow incoming connections, making it useless as a firewall. This is therefore a non-starter.
iv) Accept that your program doesn’t work with clients behind routers. You can ask the user to do manual port forwarding on his or her router (if they have one), to get round the problem.
If you want your application to “just work” it really comes down to option i) or ii).
If you are running a business with a permanently on internet connection, then these are easily possible (especially i) ). However if this is a home project, then to keep costs down, you either need to implement a server using PHP/mySQL and use polling to get game state (only suitable for turn based games) or you need a dedicated server (either to do i) or ii) ). A cheap (but not 100% reliable) solution to getting a dedicated server is to run it on your own broadband connection at home. However you have to watch the bandwidth usage. If there is only a small amount of client-client data communication then the client-server architecture works well and allows you to implement game logic in a central location as well. However if there is a lot of client-client communication, routing it through your server is slower & uses a lot of your bandwidth, in which case peer-peer using UDP Punchthrough is more attractive.
Note that in this case you lack a central server, which means all the game logic has to be in the clients. This can be a problem in some sorts of games. Also note that if you do multiplayer peer-peer, the bandwidth required by the client rises more quickly as more players are added, compared to a client-server architecture. Shouldn’t be a problem with one-on-one type games though.
As you noted, UDP is not a reliable protocol. Thus if you use UDP punchthrough & need reliable transfer, you need to write your own layer on top to do the queuing and retries.
For a simple turn based game, you are probably best off with option i) above. A dedicated server would be easiest, but you might be able to do something using PHP/mySQL (or a servlet) by having each client poll at a given rate (not to fast) to get current game state.
Alan