Jump to content


Photo

UDP Hole Punch / NAT Traversal in GM:S

gm:studio

  • This topic is locked This topic is locked
6 replies to this topic

#1 local306

local306

    GMC Member

  • GMC Member
  • 104 posts
  • Version:GM:Studio

Posted 01 July 2015 - 10:23 PM

I'm feeling defeated after many different approaches and researching how to UDP hole punch in GM:S. Has anyone had any success with this using standard GM:S networking functions, and not relying on extensions like 39 DLL or C++ servers? I've read all sorts of older posts, but I am curious if someone has had succeeded with this using the stock networking functions.

 

I am using a combination of UDP and TCP functions to coordinate online functionality for my current project. So far I have built a sign up / log in menu system. Knowing how GM:S locks up for several seconds when attempting a dead TCP socket connection, I thought I would be smart and have the client ping the server first via a UDP message and only connect when it hears something back. The problem is that unless the client has port forwarded a specific port for listening for the server's UDP return message, nothing will ever return and the connection never happens.

 

As an example, here is how I have approached the situation and say we map the following ports (illustrative purposes only):

  • Client_UDP = 123
  • Server_UDP = 456
  • Server_TCP = 789

When client attempts connection, have them create a UDP server listening on port 123. Knowing the server is listening for UDP messages on port 456, send message to this port. Server hears message and replies to client via port 123. Client hears UDP reply and creates TCP socket looking for server port 789.

 

This is fine and all, but as I said before, unless the client has port forwarded port 123, the message will never get back. I would like (if possible) not to burden the player with having to port forward, but it would be awesome to get the quick UDP feedback before attempting a TCP connection.

 

While debugging on the server side, using the async_load map to look up incoming IPs and ports, I can see the ephemeral port used by the client (usually in the range 49152 through 65535 as expected). One problem is that if the server responds directly to this port, the message will not make it back to the client. I'm assuming that for whatever reason it doesn't translate back to the original port (123) or the client is still listening on 123 and the returned message is ignored.

 

This is pretty much where I am stuck for now, hence why I am curious to know if any one has figured a way around this.

 

I have a theory that if there was a way to get the ephemeral port on the client side, you could create a new UDP server on the client's end to listen for the server's return message assuming everything happens before the port closes. I'm currently looking for a JSON API or something that I can ping which would return the ephemeral port since the HTTP functions don't need port forwarding.


  • 0

#2 Sycosplat

Sycosplat

    GMC Member

  • GMC Member
  • 34 posts
  • Version:GM:Studio

Posted 15 July 2015 - 09:20 AM

I have successfully done UDP Hole Punching using only the built-in networking functions just a few days ago.

 

I made a separate project to act as a Master Server and luckily, my home connection has a static IP.

UDP Hole Punching requires a MITM server with open ports, though. I have not heard about a technique that can achieve this without one.

 

So when a player launches a game, it first reports to a master server, which stores the IP/Port of all the clients. When a client wants to communicate with another, it has to send a request to the master server.

 

I can go into more detail, but unless you have a master server running with open ports, I don't think it can be done.

 

In regards with the TCP hanging, I struggled with that as well. First I used the function

network_set_config(network_config_connect_timeout,20);

Which seems to help a little, but it still hangs, which is obviously unacceptable in a consumer product, so personally I switched to an all-UDP system.

 

 

 

I thought I would be smart and have the client ping the server first via a UDP message and only connect when it hears something back. The problem is that unless the client has port forwarded a specific port for listening for the server's UDP return message, nothing will ever return and the connection never happens.

 

This idea will work perfectly fine if the server's ports are open. If the client sends a UDP packet, it uses let's say 43443 to send. It sends the packet to the server. For the next 120 seconds or so (depending on the router/NAT) the client's NAT will accept any packets on 43443 from the server IP/Port combination (endpoint). That is basically how hole punching works.

 

So this Sign Up/Log In system or yours, is it being run on a port that has been forwarded on that machine. There is no other way around it.

 

TL;DR Ports have to be open somewhere to initialize this whole system.


Edited by Sycosplat, 15 July 2015 - 10:23 AM.

  • 1

#3 Parakoopa

Parakoopa

    GMC Member

  • GMC Member
  • 305 posts
  • Version:GM:Studio

Posted 21 July 2015 - 11:10 PM

I have a basic GML based solution out for quite some time now, and it's open source if you want to use / change it.

 

http://gmnet.parakoopa.de/punch

 

It's using a third master server to make the connection http://gmnet.parakoopa.de/gatepunch. Here's how it works (MASTER needs forwarded ports):

 

1. GAME SERVER (GS) connects via TCP to MASTER SERVER (M) (used for communication between M and GS)

2. GS sends UDP packet to M. M notes the public UDP endpoint.

3. A CLIENT (GC) requests server with the IP of GS's server. It connects via TCP to M (again for communication)

4. GC also sends UDP packet to M, M notes the public UDP endpoint of GC

5. M sends GC's UDP port to GS.

6. M sends GS's UDP port to GC

7. GC and GS flood their UDP ports with packets. The hole is punched.

 

I always love to hear some feedback our own approaches, so tell me what you think.


  • 0

verysmall.png

Multiplayer tools for Game Maker


#4 BloodCorn

BloodCorn

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM:Studio

Posted 07 January 2016 - 10:40 PM

I'm sorry for reopening this old post, but with the 

var ip = async_load[? "ip"];

and

var port = async_load[? "port"];

you can do:

network_send_udp(socket,ip,port,buffer,buffer_tell(buffer));

Good luck! 


  • 0

#5 IuriPsyke

IuriPsyke

    GMC Member

  • GMC Member
  • 82 posts

Posted 08 January 2016 - 01:01 AM

Since this post was reopened, I would like to know what are the steps to implement this system on my game?

I made all the network functionality using TCP and it works pretty well using Hamachi or Evolve, the problem is that the players needs to download these third party softwares and some people just give up on the multiplayer.

 

Here's how my game works right now (it's the basic client<->server stuff):

The player has two options: "Host Game" or "Join Game". When he or she hosts a game, it becomes the server, and when the player joins a game, it becomes the client (of course). So let's say I want to buy or rent a Dedicated Server, do I need to rewrite the multiplayer system or do I just need to create another program to act as a Master Server?


  • 0

#6 icey379

icey379

    GMC Member

  • Banned Users
  • 346 posts
  • Version:GM:Studio

Posted 29 January 2016 - 09:45 PM

Since this post was reopened, I would like to know what are the steps to implement this system on my game?

I made all the network functionality using TCP and it works pretty well using Hamachi or Evolve, the problem is that the players needs to download these third party softwares and some people just give up on the multiplayer.

 

Here's how my game works right now (it's the basic client<->server stuff):

The player has two options: "Host Game" or "Join Game". When he or she hosts a game, it becomes the server, and when the player joins a game, it becomes the client (of course). So let's say I want to buy or rent a Dedicated Server, do I need to rewrite the multiplayer system or do I just need to create another program to act as a Master Server?

They DO NOT need to do that, all they have to do is port forward then host on that port...
Well if you can't port forward, you don't deserve to play multiplayer games anyway. (True, I was able to start hosting and playing with friends at last only after I learned how to port forward...)



#7 lolslayer

lolslayer

    GMC Member

  • GMC Member
  • 242 posts
  • Version:GM:Studio

Posted 04 February 2016 - 03:46 PM

 

Since this post was reopened, I would like to know what are the steps to implement this system on my game?

I made all the network functionality using TCP and it works pretty well using Hamachi or Evolve, the problem is that the players needs to download these third party softwares and some people just give up on the multiplayer.

 

Here's how my game works right now (it's the basic client<->server stuff):

The player has two options: "Host Game" or "Join Game". When he or she hosts a game, it becomes the server, and when the player joins a game, it becomes the client (of course). So let's say I want to buy or rent a Dedicated Server, do I need to rewrite the multiplayer system or do I just need to create another program to act as a Master Server?

They DO NOT need to do that, all they have to do is port forward then host on that port...
Well if you can't port forward, you don't deserve to play multiplayer games anyway. (True, I was able to start hosting and playing with friends at last only after I learned how to port forward...)

 

Disagree, it's way easyer if a game where you can host something yourself in-game is capable of UDP, then nearly everybody is able to host and play without much effort


  • 0





Also tagged with one or more of these keywords: gm:studio