HTML5 WebSockets
ConFoo
Scott Mattocks - February 27, 2013
@scottmattocks - scott@crisscott.com https://joind.in/8129
The internet likes rainbows and unicorns. We like have a whale that vomits gold coins. We win.
Tweet, blog, email, whatever during my talk. Share ideas. Just loop me in on the conversation.
Works for the Game Show Network
Cannot get you on The Price Is Right
Likes beer
Does not mind being interupted
If you can't see, come closer.
What are WebSockets?
The goal of this technology is to provide a mechanism for browser-based
applications that need two-way communication with servers that does not
rely on opening multiple HTTP connections (e.g. using XMLHttpRequest or
<iframe>s and long polling).
- RFC 6455 (WebSocket Protocol)
HTTP was built for sharing documents. The documents it was meant to share were static.
HTTP uses headers to request data and inform the server. Headers are small compared to research papaers.
Headers have grown to crazy amounts over time. It doesn't makes sense for small data bodies.
The Internet changed a bit and people started finding ways to do other things.
WebSockets are an attempt to provide the right tool for the things people were doing already.
Techniques like Ajax and Comet were created to address these issues.
WebSockets are good for games…
If you are playing games where people interact with each other, it is good to know where they are and what they have done.
Speed of data transmission is important.
Data has to get from me, to the server, to my opponents.
If the rat I am trying to kill has been killed by someone else, but I don't know it yet, I am going to be pissed/confused.
…and monitoring…
I don't have a real time example for this one.
People don't really want to expose that information.
The whole idea between monitoring is that you know when things are heading in the wrong direction. If you don't find out until they have gone completely wrong, you are screwed.
Good monitoring options, don't add significant load to the system.
…and stock tickers…
When money is on the line, a 30 second delay could be very expensive.
This is a standard example app that I've never seen in the real world. Theoretically, this makes sense though.
Data bodies are small "symbol +.32" and frequent.
…and sports…
It's a bit early for a live demo
Hockey and basketball are fast paced with lots action happening constantly.
Football and baseball have more regular intervals.
For fast stuff, sending data frequently without polling provides a better experience.
Lots of data would show up in batches.
For slower stuff, polling is wasteful. Talk about slow pitchers.
…and collaboration…
In my experience, collaboration is a bunch of doing stuff followed by some inactivity (talking?)
Bursty traffic means lots of waste when polling.
…and real-time messaging…
Without a constant connection, you can't call it real-time
Talk about OnForce issues with notifications.
Went out in A/B test but didn't make it to full acceptance.
…and interactive interfaces…
This was a plan for GSN that didn't quite make it, but it encapsulated all of the things we've seen already.
User interaction, people would most likely move in bursts, chatting with each other.
But I can do it all with AJAX!
You can't do it efficiently enough
You can't do it fast enough
A 2011 Ford AJAX 150
AJAX uses polling.
Comet uses long polling.
Both of those have issues with blackout periods and bi-directionality.
HTTP for small data is like this truck. It has lots of stuff up front, but not a whole lot in the back.
Should I use WebSockets?
Yes if…
You need the client to send messages to the server
You need the server to send messages to the client
You or your sysadmin gets angry/angrier when the systems and networks are over worked
If you are building applications like the ones I mentioned so far you may want to consider WebSockets.
I would put a web-based Twitter client in this class.
Either you have no friends and you don't want to poll every minute, or you have a ton of fake friends and they chat way too much
So far
WebSockets are efficient
WebSockets allow bi-directional communication on the same connection
AJAX is a misuse of existing technology
Client side API [CS]
(The browser)
+
WebSocket Protocol [WSP] ;
(The browser and the server)
The following slides will have CS or WSP to indicate which side of the equation they talk about.
initiates contact
turns the messages from the server into something consumable by the user
uses the JavaScript API
The browser initiates the contact via HTTP. It would be really dangerous to allow servers to initiate contact.
It intiates contact via HTTP because you can't be sure the server speaks WebSockets. You can be mostly sure it understands HTTP.
I can now add IE to this page, but I didn't feel like it. IE 10 has WebSocket support.
Mobile and tablet support is lacking right now.
confirms the request validity
parses requests (maybe)
sends data (maybe)
What it does with the request and data is up to you
HTTP is a request/response model. Nothing happens until there is a request. The client expects that there will be a response.
WebSockets are asynchronous. You don't have to request stuff after the connection is set up. Nor do you need to send responses or acknowledge the request.
It's easy to get started CS
var url = 'ws://ws.example.com/updates';
var socket = new WebSocket(url);
That's it. This could be one line, but it doesn't look that great on a slide.
if ("WebSocket" in window)
There is an optional second argument that lists acceptable sub protocols.
An object with these properties
url
readyState
bufferedAmount
protocol
extensions
binaryType
URL is the URL you created the object with. Helpful if you have multiple connections (potentially to different hosts). If you have some call back that deals with WS objects (maybe to close one if an error shows up somewhere), you can use the URL property to see which server it was connected to.
readyState - We will see this in a minute.
bufferedAmount - This is the amount of data that is waiting to be sent. If your user's connection is slow, you can use this to figure out if you should send data or not. It isn't important that all position coordinates get to the server. It is important that the most recent coordinates get there. If you try to send more data than the buffer can handle, the connection must be closed.
protocol - This is the subprotocol that was negotiated with the server.
extensions - There aren't any yet.
binaryType - the format that will be used to give binary data to your code.
CONNECTING
OPEN
CLOSING
CLOSED
readyState tells you what is happening with your object.
Sending data with an object which isn't connected throws an exception. You can catch that exception, or you can check the object and avoid the problem.
CONNECTING (numeric value 0) - The connection has not yet been established.
OPEN (numeric value 1) - The WebSocket connection is established and communication is possible.
CLOSING (numeric value 2) - The connection is going through the closing handshake.
CLOSED (numeric value 3) - The connection has been closed or could not be opened.
Listening to the server CS
Let's start with getting data.
There are four methods you can implement. They are all event handlers that are called on specific events.
There are two methods which are available for you to call. More on that in a bit.
socket.onopen = function () {
// Process any commands that queued up
// while we were connecting.
var i = 0, size = this.queue.length;
for (i; i < size; i++) {
this.send(this.queue[i]);
}
// Clear the command queue.
this.queue = [];
};
Queuing things up isn't required and it may not make sense for your application.
Having an onopen handler isn't required either, but its there if you need it.
socket.onmessage = function (evt) {
// Process the message from the server
$('#datalist').appendChild(evt.data);
};
This is called when data arives from the server.
This can be called even when the object's readyState is CLOSING (but not when it is closed).
socket.onerror = function () {
// Something bad happened. Log a message.
console.log('WebSocket error');
};
No arguments are given.
Could be something like a frame that said it had 100 bytes but really has 102
Not called for failed connections.
socket.onclose = function (evt) {
// Check to see if the close was clean.
if (!evt.wasClean) {
console.log('WebSocket error');
}
};
Called when the connection is closed (completely).
Event has wasClean attribute. It is clean IFF the closing handshake was completed.
The closing handshake is something we will see later, but basically make sure that both ends get to go through a nice proper shutdown sequence.
There are code and reason attributes too. Those come from the server in the closing handshake frame.
Talking to the server
Image Credit: kitcowan
WebSockets are bi-direcitonal. It isn't fun just to listen, you need to talk too.
Remember this?
The goal of this technology is to provide a mechanism for browser-based
applications that need two-way communication with servers that does not
rely on opening multiple HTTP connections (e.g. using XMLHttpRequest or
<iframe>s and long polling).
- RFC 6455 (WebSocket Protocol)
Communication is two-way, but not synchronous. Just because you send something doesn't mean you will get something back. That is why the onmessage method is a callback. It gets fired when data arives, not when you send data.
It is up to you to figure out how responses are tied to requests (if at all).
socket.send('This message is awesome!');
This example sends a string. You can also send binary data.
You can send Blob, ArrayBuffer, or ArrayBufferView objects. For example, data from a canvas element.
socket.close();
If you call close, don't call send again.
This initiates the closing handshake. That doesn't mean you won't still receive data from onmessage.
So far
Support is evolving (mostly there)
Event driven model for listening to the server
Sending data is a simple method call
Now lets look at the protocol itself.
It all starts with a (secret) handshake
The handshake is designed to make sure both ends speak the same language and do it securely.
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
It starts as HTTP, but it changes to WS.
The key is the upgrade header. This appears to go against what I said earlier about headers being bloat.
If you are sending and receiving lots of data, this small bit of overhead is a reasonable price to pay.
WebSocket Handshake Response WSP
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Creating Sec-WebSocket-Accept
$key = 'dGhlIHNhbXBsZSBub25jZQ==';
$magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$sha1 = sha1($key . $magic, true);
$accept = base64_encode($sha1);
The server proves its serveriness by computing a hash based off of the requested data.
$magic is a hard coded value chosen because it is unlikely to be chosen.
Provide a layer of security for the message
Identify the content types of the message
Indicate the size of the message
Allows for large messages to be sent without buffering
0 2 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
F I N
R S V 1
R S V 2
R S V 3
opcode (4)
M A S K
Payload len (7)
Extended payload length (16/63) (if payload len==126/127)
Extended payload length continued, if payload len == 127
Masking-key, if MASK set to 1
Masking-key (continued)
Payload Data
The End (of the connection)WSP
Either end can initiate the close
Both ends must acknowledge the closing
Image Credit: mjb
Handshake establishes a reliable connection
Message framing allows long messages to be broken into smaller chunks
Clean close requires help from both ends
Bi-directional communication
Lower overhead than HTTP
Client side is JavaScript
Protocol defines how the connection is opened and messages are sent
We're Hiring!
Great Benefits
Unlimited vacation and sick time
401K matching
Hack day every 5 weeks
No Such Thing as Routine
DAUs measures in millions
Web, Mobile, and Social
PHP, Perl, Unity, Objective-C, Java, MongoDB…
Locations
Waltham, MA — Washington, D.C. — San Francisco, CA — Your house
We sponsor visas