Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
WebSockets (confoo)
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Igor Wiedler
March 02, 2012
Programming
1.2k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
WebSockets (confoo)
Igor Wiedler
March 02, 2012
More Decks by Igor Wiedler
See All by Igor Wiedler
Redis Bedtime Stories
igorw
1
380
Wide Event Analytics (LISA19)
igorw
4
960
a day in the life of a request
igorw
0
180
production: an owner's manual
igorw
0
200
The Power of 2
igorw
0
360
LISP 1.5 Programmer's Manual: A Dramatic Reading
igorw
0
500
The Moral Character of Software
igorw
1
330
interdisciplinary computing (domcode)
igorw
0
330
miniKanren (clojure berlin)
igorw
1
340
Other Decks in Programming
See All in Programming
Security issues being discussed on Web Platforms
petamoriken
0
1.4k
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
130
wkhtmltopdfの次どうするか問題2026
willnet
2
1.8k
パーソナライズPodcastを作った話
repunit11
0
120
setup-vp GitLab対応の裏側
naokihaba
0
150
iOSDC2026登壇資料.pdf
riofujimon
0
210
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.5k
APNsからLive Activityを開始する話
yumnumm
0
150
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
900
Java 27新機能 / Java 27 new features
kishida
2
200
Rでドレミ/Do-Re-Mi_with_R
florets1
0
120
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
620
Featured
See All Featured
Design in an AI World
tapps
1
350
How to train your dragon (web standard)
notwaldorf
96
6.8k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
320
Code Reviewing Like a Champion
maltzj
528
40k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.2k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Are puppies a ranking factor?
jonoalderson
2
4k
How to Ace a Technical Interview
jacobian
280
24k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.7k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Transcript
WEBSOCKETS Friday, March 2, 12
• phpBB • Symfony2 • Silex • Composer igorw @igorwesome
Friday, March 2, 12
Friday, March 2, 12
Friday, March 2, 12
WEBSOCKETS Friday, March 2, 12
WEB Friday, March 2, 12
Application HTTP Presentation TCP Session TCP Transport TCP Network IP
Data Link Physical Friday, March 2, 12
Application HTTP Presentation TCP Session TCP Transport TCP Network IP
Data Link Physical Friday, March 2, 12
HTTP Friday, March 2, 12
client Friday, March 2, 12
request client Friday, March 2, 12
reponse client request Friday, March 2, 12
THIS IS A GOOD THING Friday, March 2, 12
BUT Friday, March 2, 12
NOT FOR EVERYTHING Friday, March 2, 12
UNIDIRECTIONAL Friday, March 2, 12
Friday, March 2, 12
LATENCY Friday, March 2, 12
STATELESS Friday, March 2, 12
Application HTTP Presentation TCP Session TCP Transport TCP Network IP
Data Link Physical Friday, March 2, 12
Application HTTP Presentation TCP Session TCP Transport TCP Network IP
Data Link Physical Friday, March 2, 12
WEBSOCKETS Friday, March 2, 12
SOCKETS Friday, March 2, 12
WEBSOCKETS Friday, March 2, 12
PROTOCOL API Friday, March 2, 12
THE WEBSOCKET PROTOCOL Friday, March 2, 12
browser Friday, March 2, 12
Friday, March 2, 12
Friday, March 2, 12
Friday, March 2, 12
• Handshake / Upgrade • TCP • Proxies • Supports
TLS (SSL) Friday, March 2, 12
Friday, March 2, 12
RFC 6455 Friday, March 2, 12
COMET Friday, March 2, 12
THE WEBSOCKET API Friday, March 2, 12
browser Friday, March 2, 12
Friday, March 2, 12
var ws = new WebSocket('ws://example.org:8080/updates'); ws.onopen = function () {
ws.send('hello'); }; ws.onmessage = function (message) { console.log(message.data); }; Friday, March 2, 12
JS INTERFACE • WebSocket • onopen • onmessage • onerror
• onclose • binaryType • MessageEvent • data Friday, March 2, 12
browser API PROTOCOL Friday, March 2, 12
Friday, March 2, 12
• built on node.js • abstracts socket communication • supports
fallback transports Friday, March 2, 12
• session storage • namespacing • acknowledgement • broadcasting •
reconnection Friday, March 2, 12
• json serialization • heartbeats • connection ids • io.sockets
collection Friday, March 2, 12
4.0+ (2009) 6.0+ (2011) 10.70+ (2012) 5.0+ (2010) 10+ (2012)
BROWSER SUPPORT Friday, March 2, 12
4.0+ 3.0+ 10.61+ 3.0+ 5.5+ WITH SOCKET.IO Friday, March 2,
12
Friday, March 2, 12
Y U NO PHP? Friday, March 2, 12
Friday, March 2, 12
Friday, March 2, 12
$context = new ZMQContext(); $sock = $context->getSocket(ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $msg =
json_encode([ 'type' => 'debug', 'data' => ['foo', 'bar', 'baz'] ]); $sock->send($msg); Friday, March 2, 12
$context = new ZMQContext(); $sock = $context->getSocket(ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $msg =
json_encode([ 'type' => 'debug', 'data' => ['foo', 'bar', 'baz'] ]); $sock->send($msg); Friday, March 2, 12
$context = new ZMQContext(); $sock = $context->getSocket(ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $msg =
json_encode([ 'type' => 'debug', 'data' => ['foo', 'bar', 'baz'] ]); $sock->send($msg); Friday, March 2, 12
$context = new ZMQContext(); $sock = $context->getSocket(ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $msg =
json_encode([ 'type' => 'debug', 'data' => ['foo', 'bar', 'baz'] ]); $sock->send($msg); Friday, March 2, 12
Friday, March 2, 12
var io = require('socket.io').listen(8080), zmq = require('zmq'), sock = zmq.socket('sub');
sock.subscribe(''); sock.bind('tcp://*:5555'); sock.on('message', function (msg) { var event = JSON.parse(msg); io.sockets.emit(event.type, event.data); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), zmq = require('zmq'), sock = zmq.socket('sub');
sock.subscribe(''); sock.bind('tcp://*:5555'); sock.on('message', function (msg) { var event = JSON.parse(msg); io.sockets.emit(event.type, event.data); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), zmq = require('zmq'), sock = zmq.socket('sub');
sock.subscribe(''); sock.bind('tcp://*:5555'); sock.on('message', function (msg) { var event = JSON.parse(msg); io.sockets.emit(event.type, event.data); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), zmq = require('zmq'), sock = zmq.socket('sub');
sock.subscribe(''); sock.bind('tcp://*:5555'); sock.on('message', function (msg) { var event = JSON.parse(msg); io.sockets.emit(event.type, event.data); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), zmq = require('zmq'), sock = zmq.socket('sub');
sock.subscribe(''); sock.bind('tcp://*:5555'); sock.on('message', function (msg) { var event = JSON.parse(msg); io.sockets.emit(event.type, event.data); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), zmq = require('zmq'), sock = zmq.socket('sub');
sock.subscribe(''); sock.bind('tcp://*:5555'); sock.on('message', function (msg) { var event = JSON.parse(msg); io.sockets.emit(event.type, event.data); }); Friday, March 2, 12
<script src="http://localhost:8080/socket.io/socket.io.js"> </script> <script> var socket = io.connect('http://localhost:8080'); socket.on('debug', function
(data) { console.log(data); }); </script> Friday, March 2, 12
LE CODE •blog comments •chat •canvas Friday, March 2, 12
LE CODE •blog comments •chat •canvas Friday, March 2, 12
class CommentController extends Controller { public function createAction(Post $post) {
$comment = new Comment(); $comment->setPost($post); $request = $this->getRequest(); $form = $this->createForm(new CommentType(), $comment); $form->bindRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $em->persist($comment); $em->flush(); $renderedRow = $this->renderView( 'AcmeBlogBundle:Comment:row.html.twig', array('comment' => $comment) ); return new Response($renderedRow, 201); } return new Response('{}', 400, array('Content-Type' => 'application/json')); } } Friday, March 2, 12
class CommentController extends Controller { public function createAction(Post $post) {
$comment = new Comment(); $comment->setPost($post); $request = $this->getRequest(); $form = $this->createForm(new CommentType(), $comment); $form->bindRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $em->persist($comment); $em->flush(); $renderedRow = $this->renderView( 'AcmeBlogBundle:Comment:row.html.twig', array('comment' => $comment) ); return new Response($renderedRow, 201); } return new Response('{}', 400, array('Content-Type' => 'application/json')); } } Friday, March 2, 12
Secret Sauce Friday, March 2, 12
private function publishCommentCreate(Comment $comment) { $context = new \ZMQContext(); $sock
= $context->getSocket(\ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $renderedRow = $this->renderView( 'AcmeBlogBundle:Comment:row.html.twig', array('comment' => $comment) ); $postId = $comment->getPost()->getId(); $msg = json_encode(array( 'type' => "post.$postId.comment.create", 'data' => $renderedRow, )); $sock->send($msg); } Friday, March 2, 12
private function publishCommentCreate(Comment $comment) { $context = new \ZMQContext(); $sock
= $context->getSocket(\ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $renderedRow = $this->renderView( 'AcmeBlogBundle:Comment:row.html.twig', array('comment' => $comment) ); $postId = $comment->getPost()->getId(); $msg = json_encode(array( 'type' => "post.$postId.comment.create", 'data' => $renderedRow, )); $sock->send($msg); } Friday, March 2, 12
private function publishCommentCreate(Comment $comment) { $context = new \ZMQContext(); $sock
= $context->getSocket(\ZMQ::SOCKET_PUB); $sock->connect('tcp://127.0.0.1:5555'); $renderedRow = $this->renderView( 'AcmeBlogBundle:Comment:row.html.twig', array('comment' => $comment) ); $postId = $comment->getPost()->getId(); $msg = json_encode(array( 'type' => "post.$postId.comment.create", 'data' => $renderedRow, )); $sock->send($msg); } Friday, March 2, 12
$this->publishCommentCreate($comment); Friday, March 2, 12
var socket = io.connect('http://localhost:8080'); socket.on('post.'+postId+'.comment.create', function (data) { renderComment(data); });
Friday, March 2, 12
LE CODE •blog comments •chat •canvas Friday, March 2, 12
<div class="messages"></div> <form> <input type="text" name="message"> <button type="submit">Send</button> </form> <script
src="http://localhost:8080/socket.io/socket.io.js"></script> <script src="jquery-1.7.min.js"></script> <script src="chat.js"></script> Friday, March 2, 12
var socket = io.connect('http://localhost:8080'), messages = $('.messages'); socket.on('message', function (message)
{ var messageHtml = $('<div></div>').text(message.body); messages.append(messageHtml); messages.prop('scrollTop', 100000); }); Friday, March 2, 12
var socket = io.connect('http://localhost:8080'), messages = $('.messages'); socket.on('message', function (message)
{ var messageHtml = $('<div></div>').text(message.body); messages.append(messageHtml); messages.prop('scrollTop', 100000); }); Friday, March 2, 12
var form = $('form'); form.submit(function (event) { event.preventDefault(); var input
= form.find('*[name=message]'), body = input.val(); if (!body.length) { return; } socket.emit('message', { name: name, body: body }); input.val(''); }); Friday, March 2, 12
var form = $('form'); form.submit(function (event) { event.preventDefault(); var input
= form.find('*[name=message]'), body = input.val(); if (!body.length) { return; } socket.emit('message', { name: name, body: body }); input.val(''); }); Friday, March 2, 12
var io = require('socket.io').listen(8080); io.sockets.on('connection', function (socket) { socket.on('message', function
(message) { io.sockets.emit('message', message); }); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), messages; messages = []; io.sockets.on('connection', function
(socket) { messages.forEach(function (message) { socket.emit('message', message); }); socket.on('message', function (message) { io.sockets.emit('message', message); messages.push(message); }); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), messages; messages = []; io.sockets.on('connection', function
(socket) { messages.forEach(function (message) { socket.emit('message', message); }); socket.on('message', function (message) { io.sockets.emit('message', message); messages.push(message); }); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), bufferLimit = 15, messages; messages =
[]; io.sockets.on('connection', function (socket) { messages.forEach(function (message) { socket.emit('message', message); }); socket.on('message', function (message) { io.sockets.emit('message', message); messages.push(message); if (messages.length > bufferLimit) { messages = messages.splice(-bufferLimit, bufferLimit); } }); }); Friday, March 2, 12
var io = require('socket.io').listen(8080), bufferLimit = 15, messages; messages =
[]; io.sockets.on('connection', function (socket) { messages.forEach(function (message) { socket.emit('message', message); }); socket.on('message', function (message) { io.sockets.emit('message', message); messages.push(message); if (messages.length > bufferLimit) { messages = messages.splice(-bufferLimit, bufferLimit); } }); }); Friday, March 2, 12
LE CODE •blog comments •chat •canvas Friday, March 2, 12
USE CASES •Games •Notifications •Collaboration •Statistics •Chat Friday, March 2,
12
PUB/SUB Friday, March 2, 12
Push only? Friday, March 2, 12
EventSource. Friday, March 2, 12
LINKS • tools.ietf.org/html/rfc6455 • dev.w3.org/html5/websockets • developer.mozilla.org/en/WebSockets • socket.io •
github.com/igorw/websockets-talk Friday, March 2, 12
github.com/igorw/websockets-talk Friday, March 2, 12
CREDITS • thenounproject.com • stopwatch • lightning • sync •
refresh Friday, March 2, 12
Questions? @igorwesome speakerdeck.com /u/igorw joind.in/5997 Frögli? Friday, March 2, 12