Una Aplicación Usando Websockets en la que Múltiples Clientes Dibujan en un Lienzo

server.rb

[19:36][~/srcSTW/streaming/websocketsDrawEM(master)]$ cat -n server.rb 
     1  require 'em-websocket'
     2  require 'json'
     3  require 'sinatra/base'
     4  
     5  EventMachine.run {
     6    @channel = EM::Channel.new
     7    @users = {}
     8    @messages = []
     9  
    10    EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
    11        
    12      ws.onopen {
    13        #Subscribe the new user to the channel with the callback function for the push action
    14        new_user = @channel.subscribe { |msg| ws.send msg }
    15        
    16        #Add the new user to the user list
    17        @users[ws.object_id] = new_user
    18        
    19        #Push the last messages to the user
    20        @messages.each do |message|
    21          ws.send message
    22        end
    23     }
    24  
    25      ws.onmessage { |msg|
    26        
    27        #append the message at the end of the queue
    28        @messages << msg
    29        @messages.shift if @messages.length > 10
    30  
    31        #Broadcast the message to all users connected to the channel
    32        @channel.push msg
    33      }
    34  
    35      ws.onclose { 
    36        @channel.unsubscribe(@users[ws.object_id])
    37        @users.delete(ws.object_id)
    38      }
    39    end
    40  
    41    #Run a Sinatra server for serving index.html
    42    class App < Sinatra::Base
    43      set :public_folder, settings.root
    44      
    45      get '/' do
    46        send_file 'index.html'
    47      end
    48    end
    49    App.run!
    50  }

index.html.haml

!!! 5
%html
  %head
    %meta(charset="utf-8")
    %meta(content="IE=edge,chrome=1" http-equiv="X-UA-Compatible")
    %meta(name="viewport" content="width=device-width, user-scalable=0, initial-scale=1.0, maximum-scale=1.0;")  
    %link(rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css")
    %script(type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js")
    %script(type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js")
    %title
      WebSockets Drawing
  %body
    :javascript
      var WebSocket = window.WebSocket || window.MozWebSocket;

      $(function() {

        var socket = new WebSocket("ws://" + location.hostname + ":8080");
       
        var currentX = 0;
        var currentY = 0;
        var lastX;
        var lastY;
        var lastReceivedX;
        var lastReceivedY;
        
        var ctx = $('#canvas')[0].getContext('2d');

        $('#canvas').bind('vmousemove',function(ev){
          ev = ev || window.event;
          currentX = ev.pageX || ev.clientX;
          currentY = ev.pageY || ev.clientY;
        });
        
        socket.onopen = function(event) {
          setInterval(function(){
            if(currentX !== lastX || currentY !== lastY){
              lastX = currentX;
              lastY = currentY;
              socket.send( JSON.stringify({x:currentX, y: currentY}) );
            }
          }, 30); // send every 300 milliseconds if position has changed
        }
        socket.onmessage = function(event) {
          var msg = $.parseJSON(event.data);
          
          ctx.beginPath();
          ctx.moveTo(lastReceivedX,lastReceivedY);
          ctx.lineTo(msg.x,msg.y);
          ctx.closePath();
          ctx.stroke();
          lastReceivedX = msg.x;
          lastReceivedY = msg.y;
        }
      });

    %div(data-role="page")
      %canvas#canvas(width='1000' height='1000')

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8' />
    <meta content='IE=edge,chrome=1' http-equiv='X-UA-Compatible' />
    <meta content='width=device-width, user-scalable=0, initial-scale=1.0, maximum-scale=1.0;' name='viewport' />
    <link href='http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css' rel='stylesheet' />
    <script src='http://code.jquery.com/jquery-1.6.4.min.js' type='text/javascript'></script>
    <script src='http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js' type='text/javascript'></script>
    <title>
      WebSockets Drawing
    </title>
  </head>
  <body>
    <script type='text/javascript'>
      //<![CDATA[
        var WebSocket = window.WebSocket || window.MozWebSocket;
        
        $(function() {
        
          var socket = new WebSocket("ws://" + location.hostname + ":8080");
         
          var currentX = 0;
          var currentY = 0;
          var lastX;
          var lastY;
          var lastReceivedX;
          var lastReceivedY;
          
          var ctx = $('#canvas')[0].getContext('2d');
        
          $('#canvas').bind('vmousemove',function(ev){
            ev = ev || window.event;
            currentX = ev.pageX || ev.clientX;
            currentY = ev.pageY || ev.clientY;
          });
          
          socket.onopen = function(event) {
            setInterval(function(){
              if(currentX !== lastX || currentY !== lastY){
                lastX = currentX;
                lastY = currentY;
                socket.send( JSON.stringify({x:currentX, y: currentY}) );
              }
            }, 30); // send every 300 milliseconds if position has changed
          }
          socket.onmessage = function(event) {
            var msg = $.parseJSON(event.data);
            
            ctx.beginPath();
            ctx.moveTo(lastReceivedX,lastReceivedY);
            ctx.lineTo(msg.x,msg.y);
            ctx.closePath();
            ctx.stroke();
            lastReceivedX = msg.x;
            lastReceivedY = msg.y;
          }
        });
      //]]>
    </script>
    <div data-role='page'>
      <canvas height='1000' id='canvas' width='1000'></canvas>
    </div>
  </body>
</html>

Figura: Múltiples clientes pueden dibujar en el lienzo
[scale=0.7]sinatra/chapter2fundamentos/websockets.png



Subsecciones
Casiano Rodriguez León 2015-01-07