• Hey! Guest! The 39th GMC Jam will take place between November 26th, 12:00 UTC and November 30th, 12:00 UTC. Why not join in! Click here to find out more!

GML How To Properly Disconnect A GML Client From A Node.JS Server

WanSou

Member
Hey, i am trying to disconnect a gml client from a node.js server
but whenever i try to disconnect it by using "network_destroy()"
the node.js server crashes and returns
" Error: read ECONNRESET "

Which from my research is because the connection was abruptly disconnected
so... how do i "propely" disconnect the gml client from the node.js server so it doesnt crash ?

note :
i am really new to networking and node.js
so dont expect much from me
ask for any information that you need to solve this issue and i will provide.

here is the full error
1600783016899.png
 

rytan451

Member
Hmm. It looks like you're getting an exception because you're attempting to read data, and either there's no data available, or the data includes a null character. What's on line 292 in events.js (if you wrote events.js)? Otherwise, if you didn't write events.js, what's the callstack leading down to that line of code?
 

WanSou

Member
Hmm. It looks like you're getting an exception because you're attempting to read data, and either there's no data available, or the data includes a null character. What's on line 292 in events.js (if you wrote events.js)? Otherwise, if you didn't write events.js, what's the callstack leading down to that line of code?
uh... i do not have a file called "events.js"
so i have no idea where to find it...
also i have no idea whats a callstack...
could you explain everything like you would to a 5 y/o ?
Im really new to node.js and im not used to anything like that

if this helps, this is my current node.js server code...

JavaScript:
var net = require("net");
var port = 6000;
 
var server = net.createServer();
let clients = []
 
 
server.on("connection",function(socket)
{
    //Enums and stuff
    var INIT = 0
    var PLAYER_UPDATE = 1
    var PLAYER_MOVED = 2
    var PLAYER_JOINED = 3
    var I_JOINED = 4
 
    //Checking the address
    var addr = socket.remoteAddress;
    console.log("New Connection: " + addr);
 
    //Clients List
    let clientAdd = clients.push(socket)
 
    //Sending the init to the connected socket/client
    var buf = Buffer.alloc(2);
    buf.writeInt8(INIT, 0);
    buf.writeInt8(clients.length,1);
    socket.write(buf);
 
    //Checking if any data has been sent to us
    socket.on("data",function(data)
    {   
        //Reading the first position in the buffer to check the type of it
        var Type = data.readInt8(0)
        //Typing what type we got
        console.log("i got " + Type)
        //Checking if the type is the PLAYER_UPDATE
        if (Type == PLAYER_UPDATE) {
            //Read all the info
            var pID = data.readInt8(1)
            var _x = data.readUInt16LE(2)
            var _y = data.readUInt16LE(4)
            //Send all the info to every client except the one that has sent us the original info.
            var buf = Buffer.alloc(6)
            buf.writeInt8(PLAYER_MOVED, 0)
            buf.writeInt8(pID, 1)
            buf.writeUInt16LE(_x, 2)
            buf.writeUInt16LE(_y, 4)
            //console.log("Info Got : " + pID + " " + _x + " " + _y) /// Debug ///
            for(i = 0; i < clients.length; i++) {
                var cur = clients[i]
                if (cur != socket) {
                    cur.write(buf)
                }
 
            }
 
        }
        //Checking if the type is I_JOINED
        if (Type == I_JOINED) {
            //Looping hrough all the clients
            for(var i = 0; i < clients.length; i++) {
                //Saving the playerID which is the clients array length
                var pID = clients.length
                //Checking what socket is the current one
                var cur = clients[i]
                //If the current one isnt the one that called this event
                if (cur != socket) {
                    //Send the info to the socket that the player has joined
                    var buf = Buffer.alloc(2)
                    buf.writeInt8(PLAYER_JOINED,0)
                    buf.writeInt8(pID, 1)
                    cur.write(buf)
                }
            }
        }
    });
 
    //I have no idea what this does ngl
    socket.once("closed",function()
    {
        console.log("Player Disconnected: " + addr);
    });
});
//Listening to stuff ppl send us
server.listen(port,function()
{
    console.log("The Server has been Started");
});
 

rytan451

Member
Have you considered attempting putting the whole "on data" callback inside a try/catch statement?

Actually, taking a step back, have you attempted to make GMS send the string "Hello World" to the node.js server, and have the node.js server just print out what it receives? As an exercise, that is usually immensely helpful for me when attempting to get this sort of framework to work.
 

chamaeleon

Member
uh... i do not have a file called "events.js"
so i have no idea where to find it...
also i have no idea whats a callstack...
could you explain everything like you would to a 5 y/o ?
Im really new to node.js and im not used to anything like that

if this helps, this is my current node.js server code...

JavaScript:
var net = require("net");
var port = 6000;

var server = net.createServer();
let clients = []


server.on("connection",function(socket)
{
    //Enums and stuff
    var INIT = 0
    var PLAYER_UPDATE = 1
    var PLAYER_MOVED = 2
    var PLAYER_JOINED = 3
    var I_JOINED = 4

    //Checking the address
    var addr = socket.remoteAddress;
    console.log("New Connection: " + addr);

    //Clients List
    let clientAdd = clients.push(socket)

    //Sending the init to the connected socket/client
    var buf = Buffer.alloc(2);
    buf.writeInt8(INIT, 0);
    buf.writeInt8(clients.length,1);
    socket.write(buf);

    //Checking if any data has been sent to us
    socket.on("data",function(data)
    { 
        //Reading the first position in the buffer to check the type of it
        var Type = data.readInt8(0)
        //Typing what type we got
        console.log("i got " + Type)
        //Checking if the type is the PLAYER_UPDATE
        if (Type == PLAYER_UPDATE) {
            //Read all the info
            var pID = data.readInt8(1)
            var _x = data.readUInt16LE(2)
            var _y = data.readUInt16LE(4)
            //Send all the info to every client except the one that has sent us the original info.
            var buf = Buffer.alloc(6)
            buf.writeInt8(PLAYER_MOVED, 0)
            buf.writeInt8(pID, 1)
            buf.writeUInt16LE(_x, 2)
            buf.writeUInt16LE(_y, 4)
            //console.log("Info Got : " + pID + " " + _x + " " + _y) /// Debug ///
            for(i = 0; i < clients.length; i++) {
                var cur = clients[i]
                if (cur != socket) {
                    cur.write(buf)
                }

            }

        }
        //Checking if the type is I_JOINED
        if (Type == I_JOINED) {
            //Looping hrough all the clients
            for(var i = 0; i < clients.length; i++) {
                //Saving the playerID which is the clients array length
                var pID = clients.length
                //Checking what socket is the current one
                var cur = clients[i]
                //If the current one isnt the one that called this event
                if (cur != socket) {
                    //Send the info to the socket that the player has joined
                    var buf = Buffer.alloc(2)
                    buf.writeInt8(PLAYER_JOINED,0)
                    buf.writeInt8(pID, 1)
                    cur.write(buf)
                }
            }
        }
    });

    //I have no idea what this does ngl
    socket.once("closed",function()
    {
        console.log("Player Disconnected: " + addr);
    });
});
//Listening to stuff ppl send us
server.listen(port,function()
{
    console.log("The Server has been Started");
});
I'm no node expert nor javascript expert, but you can try adding
JavaScript:
    socket.once("error", function(data)
    {
        console.log("Error: " + data);
    });
If this will leak the socket or not, or keep the port allocated, I have no idea presently.
 

WanSou

Member
Have you considered attempting putting the whole "on data" callback inside a try/catch statement?

Actually, taking a step back, have you attempted to make GMS send the string "Hello World" to the node.js server, and have the node.js server just print out what it receives? As an exercise, that is usually immensely helpful for me when attempting to get this sort of framework to work.
The "Sending/Recieving" information works 100%
i made it so it recieves an x,y value of the player and then sends back the values to every player so you can see him moving

and no i did not try putting the "on data" in try/catch statement
because i have no idea what that is...
sorry for my limited understanding with node.js...


I'm no node expert nor javascript expert, but you can try adding
JavaScript:
    socket.once("error", function(data)
    {
        console.log("Error: " + data);
    });
If this will leak the socket or not, or keep the port allocated, I have no idea presently.
Well, now it didnt completly crash when the client disconnected
it just said "Error: Error: read ECONNRESET"
but when the same client tried to connect again, it has outputted a different error
cmd_KOA7nrdhSB.png
and then crashed
 

rytan451

Member
I'm sorry; I was presuming that you had already learnt JavaScript syntax and language features. You should probably look up what try/catch is, in relation to JavaScript. I'm afraid I'm nowhere close to being able to explain it on a forum.

Is your node server in the file D:\nodeServer\server.js? If that's the case, then your error is on line 73 cur.write(buf). It looks like you've disconnected one of the clients. However, you're looping through the client array (line 62), which includes disconnected clients, leading to a disconnected client being sent your buffer. This is causing the error that you screenshot in your most recent post. You should probably check if the client is connected before attempting to send data to it.
 

chamaeleon

Member
@WanSou Presumably you are getting the crash because you are trying to write to a socket that has been closed due to the client disconnecting. This is probably because you haven't added code to the error handling to remove client sockets from your client array of connected sockets.
 

WanSou

Member
I'm sorry; I was presuming that you had already learnt JavaScript syntax and language features. You should probably look up what try/catch is, in relation to JavaScript. I'm afraid I'm nowhere close to being able to explain it on a forum.

Is your node server in the file D:\nodeServer\server.js? If that's the case, then your error is on line 73 cur.write(buf). It looks like you've disconnected one of the clients. However, you're looping through the client array (line 62), which includes disconnected clients, leading to a disconnected client being sent your buffer. This is causing the error that you screenshot in your most recent post. You should probably check if the client is connected before attempting to send data to it.
@WanSou Presumably you are getting the crash because you are trying to write to a socket that has been closed due to the client disconnecting. This is probably because you haven't added code to the error handling to remove client sockets from your client array of connected sockets.
I Think you were both right!
after half an hour of trying to get it working
i got it to stop crashing!

Thank You <3
 
Top