WebSocket demo

Server-side and client code to share texts and images between a server and a browser with WebSocket.

Typically, WebSocket transmits strings, although some framework appear to provide more complex objects, they are changed to string in background. To convey an object, it is placed directly in quotes into a string, or we use the stringify method. Both are used in the demo, which uses node.js and a server-side WebSocket framework, while the standard WebSocket object is used in the browser.

This demonstration is minimalist, it sends some messages between the browser and the file system, either local or remote, and transmits an image that will be displayed in a canvas tag. This provides a basic code that can be easily extended to a real application. It is better for local applications or the control of a robot from a computer or mobile (the electronic assemblies section shows how to put it in practice).

Node.js must be installed server side then the framework nodejs-websocket:

node npm nodejs-websocket

This could also be ws, or socketjs which also allows the connection between browsers, or any other library. Socket.io becomes difficult to install, It is not suitable to an introduction like this but it may be suitable for Web applications.

One exchange between the client and the server objects of the form:

{ "text" : "...a message..." }

or

{ "image" : "...path of the image on the server..." }

Another option would be to exchange a little more complex objects with a "type" property, as does the demo of Xul.fr, the type being "text" or "image".

In any case, the object is converted into a string before being transmitted, and decoded at the reception by the JSON parse method.

Server side code

var ws = require("nodejs-websocket")
var fs = require("fs")

var server = ws.createServer(function (connect) {
  console.log("Server started...")
   
  connect.on("text", function (str) {
     var jobj = JSON.parse(str);
     if("text" in jobj) {
         console.log("Received: " + jobj["text"])
         connect.sendText('{ "text": "Server connected to browser."}')
         return;
     }
     if("image" in jobj) {  
         console.log("Image asked.")
         var path ="house.png";        // for this demo, only one image
         console.log("Sending image: " + path);
         fs.exists(path, function(result) {
              var data = JSON.stringify( {'image' : path } );
              connect.sendText(data); 
         });
         return;
        }
    })

    connect.on("close", function (code) {
        console.log("Browser gone.")
    })
});

server.listen(8100)

As you can see, in the case of an image, the server checks the existence of the file and merely send the local path of the image. We will see in the client-side code that this is enough for the browser.

The image path must be relative to that of the page and not a path on the local file system, otherwise the Chrome browser will reject the assignment.

Client side JavaScript code

 var socket = new WebSocket("ws://localhost:8100");
  var canvas;
  var inner;
  window.onload=function() {
    canvas = document.getElementById("mycanvas");
    inner = document.getElementById("inner");
  }
  
  var image = new Image();
  
  function processImage(imagePath)  {       
    image.onload = function ()
    {
      // a code to resize the image is in the archive
       var context = canvas.getContext("2d");
       context.scale(scalew, scaleh);
       context.drawImage(image, 0, 0);

       // the name of the file and dimensions of the image are displayed
       var message = imagePath + ", " + ow + " x " + oh + " px";
       if(w < ow || h < oh)
        message += ", resized to " + w.toFixed() + " x "+ h.toFixed();
       document.getElementById('storage').innerHTML = message;
     }
  }

  socket.onopen = function (event) {
    socket.send('{ "text": "Browser ready!"}' ); 
  };

  socket.onmessage=function(event) { 
    var command = JSON.parse(event.data);
    for(var comm in command)
    {
      switch(comm) {
        case "text":
            document.getElementById("storage").innerHTML = command["text"];
            reak;
        case "image":
            var fname = command["image"];
            image.src= fname
            processImage(fname);
            reak;	
       }
    }
  };

  function askImage()  {
    socket.send('{ "image": ""}'); 
  }

The image is loaded by the browser by assigning the src property of the image object with the path provided by the server. Before being displayed in the canvas tag, it can receive transformations, such as a size adjustment, but the code is not shown here (it is available in the archive).

HTML code

<form action="" method="">
  <input type="button" onclick="askImage()" value="Send me an image">
</form>
<div id="inner">
<fieldset>
<div id="storage"></div>
</fieldset>
<canvas id="mycanvas"></canvas>
</div>

The complete source code is available in the archive to download ...

To launch the script, type:

node wsdemo.js

Then load the wsdemo.html page with the file explorer or the CTRL-O command of a browser.