Main forum > Tutorials
Networking for Cowards - Part 2 - Session detection
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
--- End code ---
--- 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
--- End code ---
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
--- End code ---
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.
--- End code ---
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']];
}
}
?>
--- End code ---
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
--- End code ---
... 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