Protocols used by Google Chrome:
http://blog.chromium.org/search/label/websockets
http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10
// 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
<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>
// 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( 129 ) + Chr( 4 ) + hb_StrToUtf8( "test" ) ) 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
local cMask, cMsg := "", nMaskPos := 1
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
cMask = SubStr( cData, 3, 4 )
for n = 1 to Len( SubStr( cData, 7 ) )
cMsg += Chr( nXor( Asc( SubStr( cMask, nMaskPos++, 1 ) ), Asc( SubStr( cData, 6 + n, 1 ) ) ) )
if nMaskPos == 5
nMaskPos = 1
endif
next
MsgInfo( cMsg )
// 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
<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 );
var elem = document.getElementById( 'myCanvas' );
if( elem && elem.getContext )
{
var context = elem.getContext( '2d' );
if( context )
{
context.fillRect( 0, 0, 500, 300 );
context.fillStyle = '#0f0';
context.font = '20px verdana';
context.textBaseline = 'top';
context.fillText( msg.data, 0, 0 );
}
}
}
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' )">
<canvas id="myCanvas" width="500" height="300"></canvas>
</body>
</html>
Return to FiveWin for Harbour/xHarbour
Users browsing this forum: No registered users and 75 guests