Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WebSockets and Server-Sent Events

WebSockets and Server-Sent Events

Presentation held at Framsia, a JavaScript meetup in Oslo, Norway, and BartJS, a JavaScript meetup in Trondheim, Norway.

6c51c14716e24bc1f1a3fb5ad234e773?s=128

Kim Joar Bekkelund

October 30, 2013
Tweet

More Decks by Kim Joar Bekkelund

Other Decks in Programming

Transcript

  1. WebSockets& Server-Sent Events by Kim Joar Bekkelund

  2. None
  3. None
  4. None
  5. kim joar bekkelund kimjoar.net

  6. the legacy web real-time &

  7. Polling Client Server

  8. Polling HTTP overhead per message – Polling logic in the

    client – 1 GET = 1 HTTP request and maybe data
  9. Long-polling Client Server 30s

  10. Long-polling Client Server 30s (function poll(){ $.ajax({ url: "/some-url", dataType:

    "json", timeout: 30000, success: function(data) { // handle data }, complete: poll }); })();
  11. Long-polling Client Server 30s (function poll(){ $.ajax({ url: "/some-url", dataType:

    "json", timeout: 30000, success: function(data) { // handle data }, complete: poll }); })();
  12. Long-polling Less HTTP overhead + Polling logic in the client

    – 1 GET = 1 HTTP request and often data
  13. Streaming Client Server <iframe> Transfer-Encoding: chunked append <script>

  14. Streaming “forever frame” Less HTTP overhead + Error handling –

    What’s going on? –
  15. oh, come on …

  16. WebSockets

  17. WebSockets Client Server Set up connection

  18. WebSockets Bidirectional Server and client can send and receive Full-duplex

    Server and client can send at the same time Not HTTP Minimal overhead per message Across domains No same-origin policy No constraint on payload Handles both text and binary data
  19. None
  20. None
  21. None
  22. None
  23. Simplest setup for getting started with WebSockets

  24. var ws = new WebSocket('ws://localhost:8123'); ws.onopen = function() { ws.send('yay!

    we connected!'); }; ws.onmessage = function(event) { console.log('Received from server: ' + event.data); }; HTML
  25. HTML $ python -m SimpleHTTPServer

  26. var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({ port:

    8123 }); wss.on('connection', function(ws) { ws.send('Server says hello'); ws.on('message', function(message) { console.log('Received from client:', message); }); }); app.js
  27. var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({ port:

    8123 }); wss.on('connection', function(ws) { ws.send('Server says hello'); ws.on('message', function(message) { console.log('Received from client:', message); }); }); app.js node app.js
  28. None
  29. None
  30. None
  31. None
  32. that’s it

  33. vs (W3C) WebSocket API WebSocket Protocol (IETF)

  34. WebSocket Protocol (IETF) RFC6455 “Minimalistic” protocol above TCP Starts out

    as HTTP Designed to work on port 80 and 443 Defines new URL schema: ws and wss
  35. WebSocket Protocol (IETF) Request GET / HTTP/1.1 Host: localhost:8123 Origin:

    http://localhost:8000 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 Response HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
  36. WebSocket Protocol (IETF) Request Response HTTP/1.1 101 Switching Protocols Upgrade:

    websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= GET / HTTP/1.1 Host: localhost:8123 Origin: http://localhost:8000 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13
  37. HTTP WebSocket upgrade

  38. http://chimera.labs.oreilly.com/books/1230000000545/ch17.html WebSocket Protocol (IETF) 2–10 byte overhead for server-sent message

    6–14 byte overhead for client-sent message
  39. pros cons & Minimal overhead has

  40. pros cons & Minimal overhead has gzip? cookies? response code?

    caching?
  41. No metadata on every message

  42. subprotocol agree on message format No metadata on every message

  43. var ws = new WebSocket('wss://example.org/socket', ['minProtocol', 'minProtocol-v2']); ws.onopen = function()

    { if (ws.protocol == 'minProtocol-v2') { // ... } else { // ... } }
  44. Use as a transport layer for standard application-level protocols?

  45. +

  46. Has no effect on the core WebSocket API

  47. PROXY & FIREWALL

  48. PROXY & FIREWALL WSS use

  49. PROXY & FIREWALL WSS use ♥ HEARTBEAT

  50. “The protocol is designed to allow for extensions, which will

    add capabilities to the base protocol.”
  51. Client Server large message No multiplexing

  52. No multiplexing Client Server Head-of-Line Blocking – all others are

    blocked large message
  53. No multiplexing Client Server Head-of-Line Blocking – all others are

    blocked “A Multiplexing Extension for WebSockets” large message
  54. No multiplexing Client Server

  55. (W3C) WebSocket API

  56. (W3C) WebSocket API W3C Candidate Recommendation "significant features are mostly

    locked"
  57. var ws = new WebSocket(url[, protocols]); ws.onopen = function(e) {

    }; ws.onmessage = function(e) { console.log(e.data) }; ws.onerror = function(e) { console.log(e.code, e.reason) }; ws.onclose = function(e) { }; ws.send(message); (W3C) WebSocket API
  58. var ws = new WebSocket(url[, protocols]); ws.onmessage = function(msg) {

    if (msg.data instanceof Blob) { processBlob(msg.data); } else { processText(msg.data); } }; (W3C) WebSocket API
  59. ws.send(message); ws.send(message); ws.send(message); ws.send(message); … ws.send(message); ws.send(message); ws.send(message); ws.send(message); if

    (ws.bufferedAmount < threshold) { ws.send(message); } THROTTLING LOW-LEVEL ABSTRACTION beware of how much data you send
  60. LOW-LEVEL ABSTRACTION send whatever you want ♥ JSON

  61. no reconnect no offline detection no encoding/decoding LOW-LEVEL ABSTRACTION handle

    everything yourself
  62. LOW-LEVEL ABSTRACTION the usual patterns

  63. Events Use WebSockets for pub/sub between client and server LOW-LEVEL

    ABSTRACTION the usual patterns
  64. Channels Group several events When >1 thing on the socket

    LOW-LEVEL ABSTRACTION the usual patterns
  65. Request/response When you need to ACK a message Or when

    you’re waiting for a success or error LOW-LEVEL ABSTRACTION the usual patterns
  66. Firehose When you want to push EVERYTHING as it’s happening

    LOW-LEVEL ABSTRACTION the usual patterns
  67. None
  68. Filter streams Register a search query, push when something matches

    LOW-LEVEL ABSTRACTION the usual patterns
  69. or just use it however you want

  70. so … what about browsers?

  71. None
  72. None
  73. ” realtime CARE-FREE it’s

  74. ” realtime CARE-FREE it’s IE 5.5+, Safari 3+, Chrome 4+,

    Firefox 3+, Opera 10.61+
  75. WebSocket Flash Socket Ajax long polling Ajax multipart streaming Forever

    iframe JSONP polling
  76. var io = require('socket.io').listen(8123); io.sockets.on('connection', function(socket) { socket.emit('meetup', { name:

    'framsia!' }); socket.on('other-event', function(data) { console.log(data); }); }); BACKEND
  77. var socket = io.connect('http://localhost:8123'); socket.on('meetup', function(data) { console.log(data); socket.emit('other-event', {

    my: 'data' }); }); FRONTEND
  78. solves many of the usual problems

  79. NO SILVER BULLET however, it’s

  80. NO SILVER BULLET however, it’s complexity maintained? new abstraction

  81. SockJS a different philosophy

  82. SockJS “The API should follow HTML5 Websockets API as closely

    as possible.” a different philosophy
  83. we live in an enterprise world these work in Node.js,

    but
  84. Java & .NET WebSockets in

  85. None
  86. None
  87. None
  88. hosted solutions?

  89. None
  90. None
  91. no definitive choices pros cons &

  92. PRODUCTION? is it ready for

  93. Check the Origin header Use random tokens and verify on

    server &
  94. when should I use WebSockets?

  95. there’s more to it than a FLASHY demo effect

  96. Server-Sent Events

  97. ≈ Streaming – hacks + some good stuff “forever frame”

  98. Server-Sent Events Client Server

  99. why? Super simple API When you only need push It’s

    just HTTP
  100. var source = new EventSource('/stream'); source.onopen = function(e) { console.log('opened');

    } source.addEventListener('open', function(e) { console.log('opened'); }, false); source.addEventListener('message', function(e) { console.log(e.data); }, false); FRONTEND
  101. var http = require('http'); var express = require('express'); BACKEND var

    app = express(); app.use(express.static('./public')); http.createServer(app).listen(8123); app.get('/stream', function(req, res) { req.socket.setTimeout(Infinity); }); res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); res.write('\n'); var messageCount = 0; setInterval(function() { messageCount++; res.write('id: ' + messageCount + '\n'); res.write('data: msg ' + messageCount + '\n\n'); }, 1000); res.write('data: testing\n\n');
  102. None
  103. None
  104. None
  105. Need more than one channel? var source = new EventSource('/stream');

    source.addEventListener('message', function(e) { console.log(e.data); }, false); source.addEventListener('userlogon', function(e) { console.log('login', e.data); }, false); REGULAR MESSAGE data: msg 1\n\n WITH EVENT NAME event: userlogon\n data: kimjoar\n\n
  106. None
  107. STOP! source.close(); Stoping the client Stoping the server Return HTTP

    status code != 200 OK
  108. and that’s about it

  109. so … what about browsers?

  110. None
  111. Server-Sent Events WebSockets Bidirectional & full duplex Better browser-support Handles

    binary data Automatic reconnect Simpler protocol Just HTTP
  112. QUESTIONS?