Daniel and I are currently testing WebSockets. The connection now remains alive! (great finding from Daniel, as we were closing the connection ourselves!)
This is the code for the server:
wsserver.prg
// HTML5 WebSockets server example
#include "FiveWin.ch"
static oWnd, oSocket, oClient
#define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
//------------------------------------------------------------------------//
function Main()
local oBar
DEFINE WINDOW oWnd TITLE "HTML5 WebSockets server"
DEFINE BUTTONBAR oBar OF oWnd _3D
DEFINE BUTTON OF oBar ACTION Server() TOOLTIP "Listen"
DEFINE BUTTON OF oBar ACTION oClient:SendData( Chr( 0 ) + "test" + Chr( 255 ) ) TOOLTIP "Talk to client"
ACTIVATE WINDOW oWnd
return nil
//------------------------------------------------------------------------//
function Server()
oSocket = TSocket():New( 2000 )
oSocket:bAccept = { | oSocket | oClient := TSocket():Accept( oSocket:nSocket ),;
oClient:Cargo := .F.,; //if handshake is valid
oClient:bRead := { | oSocket | OnRead( oSocket ) },;
oClient:bClose := { | oSocket | OnClose( oSocket ) } }
oSocket:Listen()
return nil
//------------------------------------------------------------------------//
function OnRead( oSocket )
local cData := oSocket:GetData()
local cToken
local reHead
local cContext, cKey
local cSend
LogFile( "c:\sockserv.txt", { "RECEIVING" } )
LogFile( "c:\sockserv.txt", { "==========" } )
LogFile( "c:\sockserv.txt", { Len( cData ), cData } )
LogFile( "c:\sockserv.txt", { "==========" } )
if ! oSocket:Cargo
// reHead = hb_regexComp( '^GET / HTTP/[1-9].[1-9]' )
cContext = GetContext( cData, "Sec-WebSocket-Key" )
cKey = hb_Base64Encode( hb_sha1( cContext + MAGIC_KEY, .t. ) )
cSend = "HTTP/1.1 101 Switching Protocols" + CRLF + ;
"Upgrade: websocket" + CRLF + ;
"Connection: Upgrade" + CRLF + ;
"Sec-WebSocket-Accept: " + cKey + CRLF + CRLF
oSocket:SendData( cSend )
LogFile( "c:\sockserv.txt", { "SENDING" } )
LogFile( "c:\sockserv.txt", { cSend } )
LogFile( "c:\sockserv.txt", { "==========" } )
oSocket:Cargo = .t.
else
? cData
oSocket:SendData( cData + CRLF + CRLF )
endif
return nil
//------------------------------------------------------------------------//
function OnClose( oSocket )
MsgInfo( "Client has closed!" )
oSocket:End()
oSocket = NIL
return nil
//------------------------------------------------------------------------//
static function GetContext( cData, cContext )
local nLen := Len( cContext )
local cValue := ""
local aLines := hb_ATokens( cData, CRLF )
local aSubLine
local cRow
for each cRow in aLines
if cContext $ cRow
aSubLine = hb_ATokens( cRow, ":" )
cValue = AllTrim( aSubLine[ 2 ] )
exit
endif
next
return cValue
And wstest.html (click "Connect" to connect to the server):
<html>
<script language="JavaScript">
var socket;
function connect()
{
try
{
socket = new WebSocket( "ws://localhost:2000/harbour" );
alert( '<p class="event">Socket Status: ' +
socket.readyState );
socket.onopen = function( event )
{
alert( event.data + ", Socket Status: " +
socket.readyState + ' (open)' );
}
socket.onmessage = function( msg )
{
alert( '<p class="message">Received: ' + msg.data );
}
socket.onclose = function( event )
{
alert( event.data + ', Socket Status: ' +
socket.readyState + ' (closed)' );
}
socket.onerror = function()
{
alert( '<p class="event">Socket Status: ' +
socket.readyState + ' (error)' );
}
}
catch( exception )
{
alert( '<p>Error' + exception );
}
}
function send( text )
{
try
{
socket.send( text );
alert( '<p class="event">Sent: ' + text );
}
catch( exception )
{
alert( '<p class="cant send">' );
}
}
</script>
<head>
</head>
<body>
<h1>HTML5 WebSockets test</h1>
<input type="button" value="Connect" onclick="connect()"><br>
<input type="button" value="Send" onclick="send( 'Hello world' )">
</body>
</html>