I am going to build a game which only involve two player, then it would be nature to consider connecting them directly, aka P2P networking.
The game is written in Javascript, so it WebRTC appear to be my answer. After some research, I choose to use the library called peerjs, a wrapper around the WebRTC API.
Test P2P Network
In the examples given by peerjs, I test the ‘Peer-to-Peer Cue System’, and other P2P app in the wild. It appears that the app only works when the sender and receiver are on the same host. It doesn’t work when my Mac serves as sender and Lab Desktop serves as receiver.
Dig into the code
I download the ‘Peer-to-Peer Cue System’ source code from Github to modify and get some sense. Finally I come with the following test code by following the peerjs documentation.
var peerID = document.getElementById('peerID'); var otherID = document.getElementById('otherID'); var stat = document.getElementById('status');
peer.on('open', function(id) { console.log('My peer ID is: ' + id); peerID.innerText = 'My peer ID is: ' + id ; }); // waiting for connection peer.on('connection', function(conn) { //once p2p is established otherID.innerText = "Connected with " + conn.peer ; stat.innerText = "The connection is " + conn.open ;
//open the connection conn.on('open' , function(){ stat.innerText = "Connection turned to open : " + conn.open ; }) }); </script> </html>
Result
Sender and receiver will successfully establish connection with conn become both readable and writeable on the same host.
When they need to communicate through the network, even specify the STUN server wouldn’t help. The conn will always be false, indicating it is not R/W.
STUN, TURN and Symmetrical NAT
I then think maybe it is the STUN server doesn’t work. But it turns out that the reason is I am sitting behind a symmetrical NAT.
A symmetric NAT is one where all requests from the same internal IP address and port, to a specific destination IP address and port, are mapped to the same external IP address and port. If the same host sends a packet with the same source address and port, but to a different destination, a different mapping is used.
So the STUN server can only punching the Asymmetrical NAT, by exchanging NAT mapped IP and port of P2P pair. For symmetrical NAT, a TURN server will be needed. A TURN server serves as a relay, connecting P2P pair.
That makes me give the idea of building the game via P2P communication a second thought. Since a server is a must have, the question become choosing between C/S architecture vs P2P architecture. If we use P2P architecture, the server will do nothing but forwording the traffic, but if we choose C/S architecture, the server will also response for game state computation and other stuff.
Test
Pystun3 is a Python STUN client for getting NAT type and external IP. Supports Python versions 2 and 3.
If P2P is your choice, open relay should be considered. Or you want to build your own TURN server, it is also very simple with coTURN.
Also, there is a good feer TURN provider called Metered.ca. When using TURN Credentials, beware to delete the STUN server url and use TURN servers only.
How about IPv6
Unfortunately, ISP and router doesn’t support it, hardware upgrade is difficult.