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
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
パーソナライズPodcastを作った話
repunit11
0
120
Webの地図
yosuke_furukawa
PRO
6
5k
Domain-Driven Transformation
hschwentner
2
2.3k
wkhtmltopdfの次どうするか問題2026
willnet
2
1.8k
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2.8k
プロダクトコードからライブラリの境界を見つける
elmetal
PRO
0
100
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
620
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
150
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
440
Workers Cache を知る
syumai
0
330
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
740
Heart of Swift Concurrency
koher
0
1.2k
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
580
Navigating Team Friction
lara
192
16k
GraphQLとの向き合い方2022年版
quramy
50
15k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
710
Code Reviewing Like a Champion
maltzj
528
40k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
730
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
1k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
470
Fantastic passwords and where to find them - at NoRuKo
philnash
52
4k
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