Main forum > Tutorials

Networking for Cowards - Part 2 - Session detection

(1/4) > >>

Kitty Hello:
OK, in this part of the tutorial "networking for cowards" we deal with sesstion detection. The main aim is to find a server in our LAN or the internet without having the user to type an IP address in some box.

LAN
The first thing we try is in our local network. That's pretty easy, because every network segment has a "broadcast" address. That is an IP address where you can send a UDP request to, and the request will be sent to _all_ computers connected to this network segment. Segment means, that it will stop at a router.

So, in order to find a server, we send a broadcast message "where are you" and wait for a resonse from the server.

First, we need 2 global ports and an application specific string.

--- Code: GLBasic ---// 27910 = NET... commands
GLOBAL port_server% = 27911 // UDP for broadcasts
GLOBAL port_client% = 27912 // use a different one to enable 2 processes on one machine (debug on one computer)
GLOBAL session$ = "my_program_name" // a session name -> could change that for a session list
 


--- Code: GLBasic ---// --------------------------------------------
// find a session using a broadcast
// --------------------------------------------
FUNCTION FindSession$:
        LOCAL sock%, ip$
        sock% = SOCK_UDPOPEN(port_client%) // open UDP client port (send broadcast port)
        // Uh-oh. Port is still locked from old instance (happens on iPhone sometimes)
        IF sock% <0
                SLEEP 2000
                RETURN ""
        ENDIF

        // find my own IP
        ip$ = SOCK_GETIP$(SOCK_GETIP(""))
        LOCAL ip_broadcast% = SOCK_GETIP("255.255.255.255") // 255.255.255.255 is the broadcast address of a network segment

        STDOUT "find session\n"
        FOR retry% = 1 TO 3 // retry some times - mostly works at 1st try
                LOCAL rv%, msg$
                rv% = SOCK_UDPSEND(sock%, session$+"\n"+ip$, ip_broadcast%, port_server%) // send the request
                IF rv% = -1
                        STDOUT "SOCK_UDPSEND -1\n"
                        BREAK
                ENDIF

                // wait for a response
                FOR reread% = 1 TO 10
                        rv% = SOCK_RECV(sock%, msg$, 128)
                        IF rv%>0
                                SOCK_CLOSE(sock%)
                                STDOUT "server at"+msg$+"\n"
                                RETURN msg$ // return what the server said
                        ENDIF

                        IF rv% = -1
                                STDOUT "SOCK_RECV -1\n" // connection error!
                                GOTO failed
                        ENDIF

                        IF rv% = -2 // would block, try again later
                                STDOUT "."
                                SLEEP 100
                        ENDIF
                NEXT

                // inform about multiple read loops (usually one is enough)
                SLEEP 200
        NEXT

        STDOUT "timed out\n"
        @failed:

        SOCK_CLOSE(sock%)
        RETURN ""
ENDFUNCTION
 

The server should eventually read that port and replay with "I'm here" or so.

--- Code: GLBasic ---// --------------------------------------------
// Wait for a client broadcasting a "Where are you" message.
// Then return the current IP address, so the client
// could connect.
// --------------------------------------------
FUNCTION AnnounceSession: bClose%
STATIC sock%
STATIC serverip$

        IF bClose% AND sock% // request to shut down
                SOCK_CLOSE(sock%)
                sock=0
                RETURN
        ENDIF

        IF sock% = 0
                serverip$ = SOCK_GETIP$(SOCK_GETIP("")) // open the listening port
                sock% = SOCK_UDPOPEN(port_server%)
                IF sock% <0
                        STDERR "can't host - port locked?\n"
                        END
                ENDIF
        ENDIF

        // wait for a request
        LOCAL rv%, msg$
        rv% = SOCK_RECV(sock%, msg$, 512)
        IF rv% > 0
                STDOUT "incomming broadcast, session: "+msg$+"\n"

                // compare session
                LOCAL pos% = INSTR(msg$, "\n")
                IF pos%>0
                        IF MID$(msg$, 0, pos%) = session$
                                LOCAL clientip$ = MID$(msg$, pos%+1, -1)
                                LOCAL clientip% = SOCK_GETIP(clientip$)
                                // reply
                                STDOUT "client accepted\n"

                                // send twice - just to be sure
                                SOCK_UDPSEND(sock%, serverip$, clientip%, port_client%)
                                SLEEP 3
                                SOCK_UDPSEND(sock%, serverip$, clientip%, port_client%)
                        ENDIF
                ENDIF
        ENDIF

        IF rv=-1 // error -> reconnect
                STDOUT "announce_session - error. Try reconnect\n"
                SOCK_CLOSE(sock%)
                sock% = 0 // display error message here. (Wait for a few seconds, then retry)
        ENDIF
ENDFUNCTION
 
In out game we would use it like:


--- Code: GLBasic ---full_again:

        IF SOCK_INIT()=FALSE
                STDERR "sock init failed\n"
                PRINT lang$("No Wifi", "Kein WLan"),32,screeny-fy-8; SHOWSCREEN
                WHILE TRUE; SLEEP 1000; WEND
        ENDIF


        session_ip$ = FindSession$()
        IF LEN(session_ip$)>4 AND NETJOINGAME(session_ip$, 0)
                gIsServer%=FALSE
        ELSE
                PRINT "Hosting session", 32, 32; SHOWSCREEN
                IF NETHOSTGAME(0)
                        gIsServer%=TRUE
                        SLEEP 100
                ELSE
                        STDERR "can't host, port seems still open\n"
                        PRINT "Port busy, please wait.", 32,32; SHOOWSCREEN
                        NETSHUTDOWN
                        SLEEP 2000
                        GOTO full_again
                ENDIF
        ENDIF

// ... ok, the game is connected and on.
 

INTERNET
OK, long time no update. Here's how to find a seccion over the internet using a very simple php script:
(Uses an .ini file - no database)


--- Code: GLBasic ---<?php
  // http://www.GLBasic.com/netsession.php?session=test&host=0
        // host= 0 -> find server - return server IP if there's a session
        // host= 1 -> host new session - returns "HOSTED" on success
        // host=-1 -> stop session - I forgot if it returns something usefull

    $ses = $_GET['session'];
    session_id('glbs'.$ses);
    $host = (int)$_GET['host'];
   

    $timeout = 15*60; // [sec]
    session_start();

    if(isset($_GET['host']) && $host == 1)
    {
        // if(PHP <= 4.0.6) use $HTTP_SESSION_VARS
        $_SESSION[$ses] = $_SERVER['REMOTE_ADDR'];
        $_SESSION[$ses.'@TimE'] = time();
        echo 'HOSTED';
    }
    else if($host == -1) // stop a session
    {
        $_SESSION[$ses] = '0';
        $_SESSION[$ses.'@TimE'] = 0;
        echo 'STOPPED';
    }
    else // find a session
    {
        if (!isset($_SESSION[$ses]) || !isset($_SESSION[$ses.'@TimE']) || (int)$_SESSION[$ses.'@TimE'] < (time()-$timeout) )
        {
            echo '0';
        }
        else
        {
            // seems a good session,
            echo $_SESSION[$_GET['session']];
        }
    }
?>
 
Please feel free to use my script, but notify me, please. I might put filters in, when traffic rises to steep.

The GLBasic side of the script is easy as:

--- Code: GLBasic ---
FUNCTION FindSessionINET$:
LOCAL ip$
        // see if there is already a session
        ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=0", 0, 256)

        IF LEN(ip$)>4 THEN RETURN ip$
        RETURN ""
ENDFUNCTION


// Announce session in INET
// true/false
FUNCTION AnnounceSessionINET%: bClose%
LOCAL ip$
        IF bClose% = FALSE
                ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=1", 0, 256)
                IF ip$="HOSTED" THEN RETURN TRUE
                RETURN FALSE
        ELSE
                // tell the server to stop it
                NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=-1", 0, 256)
                RETURN TRUE
        ENDIF
ENDFUNCTION
 

... See the updated version here:
http://www.glbasic.com/forum/index.php?topic=2779.msg95840#msg95840


Schranz0r:
WOW :nw:

FutureCow:
Thanks Gernot!!!

bigsofty:
Arg, what happened to the 2ND lesson? :rant:

bigsofty:
Can anyone see Gernots post in this thread, Ive noticed a few of his posts are now blank when I read them?

Navigation

[0] Message Index

[#] Next page

Go to full version