Websockets, Ruby y Pusher Webprendedor 2010

1,252 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,252
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Websockets, Ruby y Pusher Webprendedor 2010

  1. 1. WebSockets in Ruby (and things you can do with them) Ismael Celis @ismasan github.com/ismasan new bamboo new-bamboo.co.uk pusherapp.com Friday, 19 November 2010
  2. 2. Polling Long-polling Web socket websockets.org/about.html HTML5 Web sockets Friday, 19 November 2010
  3. 3. Casos de uso •Chat •Aplicaciones financieras •Juegos •Presencia de usuarios •Colaboración •Notificaciones Tiempo Real Friday, 19 November 2010
  4. 4. WebSockets DOM API <script type="text/javascript" charset="utf-8"> // Socket object var socket = new WebSocket('ws://some.host.com'); // Callbacks socket.onopen = function (evt) { alert('Socket connected: ' + evt.data) }; // Incoming server message socket.onmessage = function (evt) { alert( evt.data ) }; socket.onclose = function (evt) { alert('Connection terminated') // reconnect, etc. }; </script> Friday, 19 November 2010
  5. 5. WebSockets handshake Request Response GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa- (draft 76) Friday, 19 November 2010
  6. 6. "x00Hello Worldxff" Mensajes // Incoming server message socket.onmessage = function (evt) { alert( evt.data ) }; // Send message to server socket.send("Hello server, this is a new client"); Friday, 19 November 2010
  7. 7. (Ruby) WebSockets server •Hablar WebSockets (handshake) •Mantener conexiones abiertas •Rendimiento •Escalable •Threads? Eventos? Friday, 19 November 2010
  8. 8. EventMachine rubyeventmachine.com require 'eventmachine' module EchoServer def receive_data(data) send_data data end end EventMachine::run { EventMachine::start_server 'localhost', 8080, EchoServer puts 'running echo server on 8080' } Friday, 19 November 2010
  9. 9. EM-WebSocket github.com/igrigorik/em-websocket EventMachine.run { EventMachine::WebSocket.start(:host=>'0.0.0.0',:port=>8080) do |socket| socket.onopen { # publish message to the client socket.send 'Websocket connection open' } socket.onmessage {|msg| # echo message to client socket.send "Received message: #{msg}" } end } Friday, 19 November 2010
  10. 10. Multicast - subscribers ... @channel = Channel.new ... socket.onopen { @channel.subscribe socket } socket.onmessage { |msg| @channel.send_message msg } socket.onclose { @channel.unsubscribe socket } Friday, 19 November 2010
  11. 11. Multicast - subscribers # Server socket.onopen { @channel.subscribe socket } class Channel def initialize @sockets = [] end def subscribe( socket ) @sockets << socket end ... end Friday, 19 November 2010
  12. 12. Multicast - channel class Channel ... def subscribe( socket ) @sockets << socket end def send_message( msg ) @sockets.each do |socket| socket.send msg end end def unsubscribe( socket ) @sockets.delete socket end end Friday, 19 November 2010
  13. 13. Multicast - ejemplo var socket = new WebSocket('ws://localhost:8080'); socket.onmessage = function( evt ) { $('<li>') .text(evt.data) .appendTo('#messages'); } <ul id="messages"> </ul> HTML Javascript Friday, 19 November 2010
  14. 14. Multicast - ejemplo github.com/ismasan/websockets_examples Friday, 19 November 2010
  15. 15. Elige tu protocolo STOMP CONNECT login: <username> passcode: <passcode> <message from=”john@server.com/ruby” to=”jane@server.com/ruby”> <body>Hey Jane!</body> </message> XMPP Your own (JSON?) Friday, 19 November 2010
  16. 16. Formato personalizado JSON Friday, 19 November 2010
  17. 17. Formato personalizado { “event”: “user_connected”, { “name” : “Ismael”, “total_users” : 10 } } Event name Custom data “data”: Friday, 19 November 2010
  18. 18. Formato personalizado { “event”: “user_message”, { “message” : “Hello!”, “date” : “23 2010 21:12:28” } } “data”: Friday, 19 November 2010
  19. 19. Javascript wrapper var socket = new FancyWebSocket('ws://localhost:8080'); ... socket.bind( 'user_connected', function (user_data) { // Add user to screen $('#connected_users').append('<li>' + user_data.name + '</li>'); }); socket.bind( 'user_message', function (msg_data) { // Add message to screen $('#messages').append('<li>' + msg_data.message + '</li>'); }); Friday, 19 November 2010
  20. 20. // Broadcast message - jQuery example $('form#user_input').submit(function () { var msg = $(this).find('input[name=message]').val(); socket.send( 'user_message', {name: 'Ismael', message: msg} ); return false; }); Javascript wrapper { “event” : “user_message”, { “name” : “Ismael”, “message” : “hello!” } } “data” : Friday, 19 November 2010
  21. 21. Implementación var FancyWebSocket = function(url){ var conn = new WebSocket(url); var callbacks = {}; this.bind = function(event_name, callback){ callbacks[event_name] = callbacks[event_name] || []; callbacks[event_name].push(callback); }; this.send = function(event_name, event_data){ var payload = JSON.stringify({event:event_name, data: event_data}); conn.send( payload ); }; // dispatch to the right handlers conn.onmessage = function(evt){ var json = JSON.parse(evt.data) dispatch(json.event, json.data) }; conn.onclose = function(){dispatch('close',null)} conn.onopen = function(){dispatch('open',null)} var dispatch = function(event_name, message){ var chain = callbacks[event_name]; if(typeof chain == 'undefined') return; // no callbacks for this event for(var i = 0; i < chain.length; i++){ chain[i]( message ) } } }; gist.github.com/299789 Friday, 19 November 2010
  22. 22. Implementación var FancyWebSocket = function(url){ var conn = new WebSocket(url); var callbacks = {}; this.bind = function(event_name, callback){ callbacks[event_name] = callbacks[event_name] || []; callbacks[event_name].push(callback); }; this.send = function(event_name, event_data){ var payload = JSON.stringify({event:event_name, data: event_data}); conn.send( payload ); }; gist.github.com/299789 Friday, 19 November 2010
  23. 23. Ismael Celis Implementación var FancyWebSocket = function(url){ var conn = new WebSocket(url); var callbacks = {}; this.bind = function(event_name, callback){ callbacks[event_name] = callbacks[event_name] || []; callbacks[event_name].push(callback); }; this.send = function(event_name, event_data){ var payload = JSON.stringify({event:event_name, data: event_d conn.send( payload ); }; // dispatch to the right handlers conn.onmessage = function(evt){ var json = JSON.parse(evt.data) dispatch(json.event, json.data) gist.github.com/299789 Friday, 19 November 2010
  24. 24. // dispatch to the right handlers conn.onmessage = function(evt){ var json = JSON.parse(evt.data) dispatch(json.event, json.data) }; conn.onclose = function(){dispatch('close',null)} conn.onopen = function(){dispatch('open',null)} var dispatch = function(event_name, message){ var chain = callbacks[event_name]; if(typeof chain == 'undefined') return; // no callbacks for this event for(var i = 0; i < chain.length; i++){ chain[i]( message ) } } Implementación WebSocket gist.github.com/299789 Friday, 19 November 2010
  25. 25. var FancyWebSocket = function(url){ // dispatch to the right handlers conn.onmessage = function(evt){ var json = JSON.parse(evt.data) dispatch(json.event, json.data) }; conn.onclose = function(){dispatch('close',null)} conn.onopen = function(){dispatch('open',null)} var dispatch = function(event_name, message){ var chain = callbacks[event_name]; // no callbacks for this event if(typeof chain == 'undefined') return; for(var i = 0; i < chain.length; i++){ chain[i]( message ) } } }; Implementación gist.github.com/299789 Friday, 19 November 2010
  26. 26. socket.send( 'user_message', {name: 'Ismael', message: msg} ); Implementación this.send = function(event_name, event_data){ var payload = JSON.stringify({event:event_name, data: event_data}); conn.send( payload ); // <= send JSON data to socket server return this; }; gist.github.com/299789 Friday, 19 November 2010
  27. 27. Multicast - datos JSON github.com/ismasan/websockets_examples Friday, 19 November 2010
  28. 28. Multicast - datos JSON $('#canvas').mousedown(function () { drawing = true; }) .mouseup(function () { drawing = false; }) .mousemove(function (evt) { if(drawing) { var point = [evt.pageX, evt.pageY]; socket.send('mousemove', point); } }); Friday, 19 November 2010
  29. 29. Multicast - datos JSON var ctx = document.getElementById ('canvas').getContext('2d'); ctx.lineWidth = 1; ctx.strokeStyle = '#ffffff'; ctx.beginPath(); ctx.moveTo(0, 0); // Listen to other user's moves socket.bind('mousemove', function (point) { ctx.lineTo(point[0],point[1]); ctx.stroke(); }); Friday, 19 November 2010
  30. 30. Panel de actividad Friday, 19 November 2010
  31. 31. Panel Rails Rumble Friday, 19 November 2010
  32. 32. Escalando ? Friday, 19 November 2010
  33. 33. pusherapp.com Friday, 19 November 2010
  34. 34. pusherapp.com Your app REST Browsers Websockets Existing HTTP Friday, 19 November 2010
  35. 35. pusherapp.com Friday, 19 November 2010
  36. 36. pusherapp.com <script src="http://js.pusherapp.com/1.6/pusher.min.js"></script> <script type="text/javascript" charset="utf-8"> var socket = new Pusher('293d8ae77496e1fc053b'); </script> Friday, 19 November 2010
  37. 37. pusherapp.com var socket = new Pusher('293d8ae77496e1fc053b'); // Subscribe to channels var channel = socket.subscribe( 'test' ); channel.bind( 'new_message', function (data) { alert( data.message ); }) Friday, 19 November 2010
  38. 38. pusherapp.com // Subscribe to PRESENCE channel var chat = socket.subscribe( 'presence-chat' ); // Listen to new members chat.bind( 'pusher:member_added', function (member) { alert( member.user_data.name ); }) Friday, 19 November 2010
  39. 39. require 'pusher' require 'sinatra' post '/messages' do message = Message.create(params[:message]) Pusher['presence-chat'].trigger(:new_message, message.attributes) redirect '/messages' end pusherapp.com $ gem install pusher Friday, 19 November 2010
  40. 40. pusherapp.com github.com/ lifo/cramp ismasan/websockets_examples newbamboo/rumbledash blog.new-bamboo.co.uk blog.pusherapp.com Friday, 19 November 2010
  41. 41. Tutorial github.com/ismasan/pusher-chat-tutorial Friday, 19 November 2010
  42. 42. Widgets var chat = pusher.subscribe('presence-chat'); new Widgets.Messages( chat ); new Widgets.Members( chat ); new Widgets.SoundAlerts( chat ); Friday, 19 November 2010
  43. 43. Widgets Widgets.Messages = function (chat) { /*------------------------------------------------------ Listen to messages -------------------------------------------------------*/ chat.bind( 'message', function (message) { $('<li>') .text(message.user + ' dice: ' + message.body) .appendTo('#messages'); }); } // new Widgets.Messages( chat ); Friday, 19 November 2010
  44. 44. github.com/ismasan/pusher-chat-tutorial pusherapp.com/demos pusherapp.com/docs Friday, 19 November 2010

×