Multiplayer with no portforwarding or server. Only two or more clients directly connecting to each other

So after seeing that other topic, I decided to test UDPHP.
TL;DR, you can circumvent the need for a server if you just connect two sockets together. And holy crap, it works... 99% of the time...

But what I'd love help with, is checking how often this works in the real world. Because there's no point implementing this if it only works 10% of the time. So all the sourcecode is here if you wanted to take a look and see whether it works for you too?

Here is what I have tested:
Two windows in a VM (sharing the same network card as host OS): WORKS
Two windows in a VM (directly using the network card): DOES NOT WORK
One window open, and another on a different machine on same wifi but using a VPN: WORKS
One window open, and another in a different house altogether: WORKS
One window open, and another on a different computer on the same network: DOES NOT WORK

But sometimes it ceases to work altogether (but that could just be me messing with my network settings).

So just create a new object with:
- a create event
- a draw event
- an asynchronous networking event
- an asynchronous http event

Then put that object in a room. Compile, then run from compiled (or if you have GM2 just launch multiple windows).
Don't forget to disable splash screen!

Code:
/// CREATE EVENT
// Create a UDP socket to listen on
listenPort = 2222;

while true
    {
    // Attempt to open socket
    listenSocket = network_create_socket_ext(network_socket_udp,listenPort);
    if listenSocket < 0
        {
        // Fail
        show_debug_message("Failed to bind to port" + string(listenPort) + ", trying next port.");
        listenPort++;
        }
    else
        {
        // Success
        show_debug_message("Listening for UDP on port " + string(listenPort));
        break;
        }
    }

// Variables
timer     = 0;                         // Don't send data every step, spread it out
otherIP   = "localhost";               // The ip we want to send to
otherPort = 2222 + (listenPort==2222); // Hacky script that detects whether another window is open locally

// Our x/y are used to draw network cursor (so hide it inially)
x = -200;
y = -200;

// Small screen so you can fit more
var w = 700; var h = 400;
window_set_size(w,h);
room_width = w; room_height = h;
surface_resize(application_surface,w,h);
window_set_caption("Port forwarding without a third party");

// Retrieve our own ip
ipRequest = http_get("http://api.ipify.org");
listenIP  = "";

Code:
/// ASYNCHRONOUS HTTP EVENT
var requestID   = ds_map_find_value(async_load,"id");          // ID originally returned from the http_get()
var result      = ds_map_find_value(async_load,"result");      // HTML of page requested
var http_status = ds_map_find_value(async_load,"http_status"); // 200 means success. Google 'http status codes' for a list

// If our IP is ready
if (requestID == ipRequest)
    {
    if http_status == 200
        {
        // Update
        listenIP = result;
        }
    else
        {
        show_debug_message("Could not get own IP address, http error code: " + string(http_status));
        }
    }
Code:
/// ASYNCHRONOUS NETWORKING EVENT
var type   = ds_map_find_value(async_load,"type");   // network_type_*
var buffer = ds_map_find_value(async_load,"buffer"); // The data received
var ip     = ds_map_find_value(async_load,"ip");     // The other person's ip
var port   = ds_map_find_value(async_load,"port");   // The other person's port
var socket = ds_map_find_value(async_load,"id");     // The game maker socket it came in on


// If this data is for us
if (socket == listenSocket and type == network_type_data)
    {
    // Update the "mouse"
    x = buffer_read(buffer,buffer_s16);
    y = buffer_read(buffer,buffer_s16);
    show_debug_message("Received data from " + ip + ":" + string(port));
    }
Code:
/// DRAW EVENT
//----------------------------------------------- UI -------------------------------------------
var yPos = 0;

// Instructions
draw_text_colour(10,20+(13*yPos++),"Instructions:",c_black,c_black,c_black,c_black,1);
draw_text_colour(10,20+(13*yPos++),"Open 2 of these windows and move the mouse over one.",c_black,c_black,c_black,c_black,1);
draw_text_colour(10,20+(13*yPos++),"It's working if you can see your cursor in the other window.",c_black,c_black,c_black,c_black,1);
draw_text_colour(10,20+(13*yPos++),"Close 1 of the windows, then:",c_black,c_black,c_black,c_black,1);
draw_text_colour(10,20+(13*yPos++),"Test if connecting to self works (localhost:" + string(listenPort) + ")",c_dkgray,c_dkgray,c_dkgray,c_dkgray,1);
draw_text_colour(10,20+(13*yPos++),"Test if connecting to self externally works (" + string(listenIP) + ":" + string(listenPort) + ")",c_dkgray,c_dkgray,c_dkgray,c_dkgray,1);
draw_text_colour(10,20+(13*yPos++),"Test if connecting to someone else on your network works",c_dkgray,c_dkgray,c_dkgray,c_dkgray,1);
draw_text_colour(10,20+(13*yPos++),"Test if connecting to someone else on the internet works (theirIP:theirPort)",c_dkgray,c_dkgray,c_dkgray,c_dkgray,1);
draw_text_colour(10,20+(13*yPos++),"Also try this: Connect two clients to each other",c_dkgray,c_dkgray,c_dkgray,c_dkgray,1);
draw_text_colour(10,20+(13*yPos++),"Then create a third client and connect 2 to 3 and 3 to /// CREATE EVENT
// Create a UDP socket to listen on
listenPort = 2222;

while true
    {
    // Attempt to open socket
    listenSocket = network_create_socket_ext(network_socket_udp,listenPort);
    if listenSocket < 0
        {
        // Fail
        show_debug_message("Failed to bind to port" + string(listenPort) + ", trying next port.");
        listenPort++;
        }
    else
        {
        // Success
        show_debug_message("Listening for UDP on port " + string(listenPort));
        break;
        }
    }

// Variables
timer     = 0;                         // Don't send data every step, spread it out
otherIP   = "localhost";               // The ip we want to send to
otherPort = 2222 + (listenPort==2222); // Hacky script that detects whether another window is open locally

// Our x/y are used to draw network cursor (so hide it inially)
x = -200;
y = -200;

// Small screen so you can fit more
var w = 700; var h = 400;
window_set_size(w,h);
room_width = w; room_height = h;
surface_resize(application_surface,w,h);
window_set_caption("Port forwarding without a third party");

// Retrieve our own ip
ipRequest = http_get("http://api.ipify.org");
listenIP  = "";

Below is two windows connected on the same machine to show concept and what the code does. White circle is the mouse, and red circle is coordinates received over the network of the mouse in a different window (used to prove data can be sent without a server).
port forwarding.gif
 
Last edited:
Top