HTML5 WebSockets example

HTML5 WebSockets example

Postby Antonio Linares » Fri Dec 23, 2011 9:59 pm

regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: OT: HTML5 WebSockets

Postby Antonio Linares » Fri Dec 23, 2011 10:07 pm

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
Code: Select all  Expand view
// 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):
Code: Select all  Expand view
<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>
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: HTML5 WebSockets example

Postby Antonio Linares » Sat Dec 24, 2011 12:27 pm

Working fine! :-)

wsserver.prg
Code: Select all  Expand view
// 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
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: HTML5 WebSockets example

Postby Antonio Linares » Sat Dec 24, 2011 1:14 pm

Image

wstest.html
Code: Select all  Expand view
<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>
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 73 guests