Web Socket 101 Shuai Zhao HTML 1 2
Web. Socket 101 Shuai Zhao
HTML 1, 2, 3, 4 • Designed at 1993 • new update until HTML 5, 2008 • Originally proposed as part of HTML 5 • IETF-defined Protocol: RFC 6455 • W 3 C defined Java. Script API
HTML 5 • HTML 5 introduces a number of new elements and attributes that helps in building a modern website. Following are great features introduced in HTML 5. • New Semantic Elements − These are like <header>, <footer>, and <section>. • Forms 2. 0 − Improvements to HTML web forms where new attributes have been introduced for <input> tag. • Persistent Local Storage − To achieve without resorting to third-party plugins. • Web. Socket − A a next-generation bidirectional communication technology for web applications. • Server-Sent Events − HTML 5 introduces events which flow from web server to the web browsers and they are called Server-Sent Events (SSE). • Canvas − This supports a two-dimensional drawing surface that you can program with Java. Script. • Audio & Video − You can embed audio or video on your web pages without resorting to third-party plugins. • Geolocation − Now visitors can choose to share their physical location with your web application. • Microdata − This lets you create your own vocabularies beyond HTML 5 and extend your web pages with custom semantics. • Drag and drop − Drag and drop the items from one location to another location on a the same webpage
Web. Socket • Web Sockets is a next-generation bidirectional communication technology for web applications which operates over a single socket and is exposed via a Java. Script interface in HTML 5 compliant browsers. • Once you get a Web Socket connection with the web server, you can send data from browser to server by calling a send() method, and receive data from server to browser by an onmessage event handler • A Web. Socket is a standard bidirectional TCP socket between the client and the server. The socket starts out as a HTTP connection and then "Upgrades" to a TCP socket after a HTTP handshake. After the handshake, either side can send data.
What’s the basic idea ? TCP based, bi-directional, full-duplex messaging Establish connection (Single TCP connection) Send messages in both direction (Bi-directional) Send message independent of each other (Full Duplex) End connection
HTTP/1. 1 • HTTP is half-duplex, a one-way communication protocol Client Polls only, Then server send • Complex, Inefficient, Wasteful • It is designed for file transfer, or server any other static resources
HTTP/1. 1 Header • Bandwidth intensive due to heavy headers • • HTTP header traffic approx. 800 to 2000 bytes overhead per request/response This amount of traffic is transferred every time you send out a HTTP request GET /a-url HTTP/1. 1 Host: www. google. com User-Agent: Mozilla/5. 0 (Windows; U; Windows NT 6. 1; en-US; rv: 1. 9. 1. 5) Gecko/20091102 Firefox/3. 5. 5 (. NET CLR 3. 5. 30729) Accept: Accept-Language: en-us, en; q=0. 5 Accept-Encoding: gzip, deflate Keep-Alive: 300 Connection: keep-alive Cookie: PHPSESSID=r 2 t 5 uvjq 435 r 4 q 7 ib 3 vtdjq 120 Pragma: no-cache Cache-Control: no-cache. . • HTTP/1. x 200 OK • Transfer-Encoding: chunked • Date: Sat, 28 Nov 2009 04: 36: 25 GMT • Connection: close • Pragma: public • . . • Content <HTML> file
HTTP 1 -4 Limitation • Evolution of web apps • Dynamic and real-time application, Net. Flix, Youtube, . . . • online stock trading, traffic monitoring • HTTP is not designed for those applications • large overhead • one-way communication, not efficiently
HTTP and Real time • HTTP Comet project: • • aim to provide HTTP Real-time polling: client send out request at regular interval long-polling: open channel over a period of time between client and server All those methods are still suffering HTTP heavy headers • Simply put, HTTP wasn’t designed for real-time, full-duplex communication
Websocket real time support for HTTP • Reduce Header size to 2 bytes!!!! • Web. Socket is a transport protocol for web applications, which support bidirectional communication between client and server
The Web. Socket Handshake
Latency comparison between the polling and Web. Socket applications
Websocket small header size efficiency Assume HTTP header is 871 bytes (some are 2000 bytes) • Use case A: 1, 000 clients polling every second: Network traffic is (871 × 1, 000) = 871, 000 bytes = 6, 968, 000 bits per second (6. 6 Mbps) • Use case B: 10, 000 clients polling every second: Network traffic is (871 × 10, 000) = 8, 710, 000 bytes = 69, 680, 000 bits per second (66 Mbps) • Use case C: 100, 000 clients polling every 1 second: Network traffic is (871 × 100, 000) = 87, 100, 000 bytes = 696, 800, 000 bits per second (665 Mbps) Regular HTTP • Use case A: 1, 000 clients receive 1 message per second: Network traffic is (2 × 1, 000) = 2, 000 bytes = 16, 000 bits per second (0. 015 Mbps) • Use case B: 10, 000 clients receive 1 message per second: Network traffic is (2 × 10, 000) = 20, 000 bytes = 160, 000 bits per second (0. 153 Mbps) • Use case C: 100, 000 clients receive 1 message per second: Network traffic is (2 × 100, 000) = 200, 000 bytes = 1, 600, 000 bits per second (1. 526 Mbps) HTTP with websocket
Websocket Interface • Server support: • • Kaazing Web. Socket Gateway—a Java-based Web. Socket Gateway mod_pywebsocket—a Python-based extension for the Apache HTTP Server Netty—a Java network framework which includes Web. Socket support node. js—a server-side Java. Script framework on which multiple Web. Socket servers have been written
Create websocket instance • var my. Web. Socket= new Web. Socket(url, [protocal] ); • Here first argument, url, specifies the URL to which to connect. • ws: // • wss: // • The second attribute, protocol is optional, and if present, specifies a subprotocol that the server must support for the connection to be successful.
Websocket Attributes • my. Web. Socket. ready. State • • • its a readonly attribute that represtents the state of the connection 0: Not ready yet 1: establish is done 2: Closing now 3: closed • my. Web. Socket. buffered. Amount: • return buffer size • its used by send()
Web. Socket Events handler • open: when websocket connection is open • my. Web. Socket. onopen • message: after connection, when there is message coming • my. Web. Socket. onmessage • error: Error message • my. Web. Socket. onerror • close: connection is closed • my. Web. Socket. onclose • exmaples // If connection is open, onopen event listener will be called my. Web. Socket. onopen = function(evt) { alert("Connection open. . . "); }; // If this is any incoming message, onmessage event listener will be called my. Web. Socket. onmessage = function(evt) { alert( "Received Message: " + evt. data); }; // if connection is closed, onclose event listener will be called my. Web. Socket. onclose = function(evt) { alert("Connection closed. "); };
Web. Socket Methods • my. Web. Socket. send() • my. Web. Socket. close()
Websocket server support • Server support: • • Kaazing Web. Socket Gateway—a Java-based Web. Socket Gateway mod_pywebsocket—a Python-based extension for the Apache HTTP Server Netty—a Java network framework which includes Web. Socket support node. js—a server-side Java. Script framework on which multiple Web. Socket servers have been written
Example • Client • Websocket with node. js
Client – save as index. html <!DOCTYPE html> <head> <meta charset="UTF-8" /> <script> "use strict"; // Initialize everything when the window finishes loading window. add. Event. Listener("load", function(event) { var status = document. get. Element. By. Id("status"); var url = document. get. Element. By. Id("url"); var open = document. get. Element. By. Id("open"); var disconnect = document. get. Element. By. Id("disconnect"); var send = document. get. Element. By. Id("send"); var text = document. get. Element. By. Id("text"); var message = document. get. Element. By. Id("message"); var socket;
status. text. Content = "Not Connected"; // Web Socket is connected, send data using send() url. value = "ws: //localhost: 8080"; message. text. Content = "Server replies: " + event. data; disconnect. disabled = true; }; send. disabled = true; socket. onerror = function(event) // Create a new connection when the Connect button is clicked { // Web Socket is connected, send data using send() open. add. Event. Listener("click", function(event) { message. text. Content = "Error: " + event; open. disabled = true; //socket = new Web. Socket(url. value, "echo-protocol"); }; socket = new Web. Socket(url. value, "testing-protocol"); socket. onopen = function() socket. onclose= function(event) { { // Web Socket is connected, send data using send() open. disabled = false; disconnect. disabled = false; status. text. Content = "Not Connected"; send. disabled = false; status. text. Content = "Connected"; }; socket. onmessage = function(event) { } });
Client // Close the connection when the Disconnect button is clicked disconnect. add. Event. Listener("click", function(event) { disconnect. disabled = true; send. disabled = true; message. text. Content = ""; socket. disconnect(); }); // Send text to the server when the Send button is clicked send. add. Event. Listener("click", function(event) { socket. send(text. value); text. value = ""; status. text. Content = "Connected!, " + "Buffered: " + socket. buffered. Amount; }); </script> </head>
Client <body> <h 1>Websocket Echo Client Example</h 1> Status: <font color="red"><span id="status" ></span></font> URL: <input id="url" /> <input id="open" type="button" value="Connect" /> <input id="disconnect" type="button" value="Disconnect" /> <input id="send" type="button" value="Send To Server" /> <input id="text" /> <span id="message"></span> </body> </html>
Server: node-server. js #!/usr/bin/env node var Web. Socket. Server = require('websocket'). server; var http = require('http'); var server = http. create. Server(function(request, response) { console. log((new Date()) + ' Received request for ' + request. url); response. write. Head(404); response. end(); }); server. listen(8080, function() { console. log((new Date()) + ' Server is listening on port 8080'); }); ws. Server = new Web. Socket. Server({ http. Server: server, auto. Accept. Connections: false });
server function origin. Is. Allowed(origin) { if (message. type === 'utf 8') { // put logic here to detect whether the specified origin is allowed. console. log('Received Message: ' + message. utf 8 Data); return true; var New_message = message. utf 8 Data + "#####" connection. send. UTF(New_message); } } else if (message. type === 'binary') { ws. Server. on('request', function(request) { if (!origin. Is. Allowed(request. origin)) { // Make sure we only accept requests from an allowed origin console. log('Received Binary Message of ' + message. binary. Data. length + ' bytes'); connection. send. Bytes(message. binary. Data); request. reject(); } console. log((new Date()) + ' Connection from origin ' + request. origin + ' rejected. '); }); connection. on('close', function(reason. Code, description) { return; } var connection = request. accept('testing-protocol', request. origin); console. log((new Date()) + ' Connection accepted. '); connection. on('message', function(message) { console. log((new Date()) + ' Peer ' + connection. remote. Address + ' disconnected. '); });
server function origin. Is. Allowed(origin) { if (message. type === 'utf 8') { // put logic here to detect whether the specified origin is allowed. console. log('Received Message: ' + message. utf 8 Data); return true; var New_message = message. utf 8 Data + "#####" connection. send. UTF(New_message); } } else if (message. type === 'binary') { ws. Server. on('request', function(request) { if (!origin. Is. Allowed(request. origin)) { // Make sure we only accept requests from an allowed origin console. log('Received Binary Message of ' + message. binary. Data. length + ' bytes'); connection. send. Bytes(message. binary. Data); request. reject(); } console. log((new Date()) + ' Connection from origin ' + request. origin + ' rejected. '); }); connection. on('close', function(reason. Code, description) { return; } var connection = request. accept('testing-protocol', request. origin); console. log((new Date()) + ' Connection accepted. '); connection. on('message', function(message) { console. log((new Date()) + ' Peer ' + connection. remote. Address + ' disconnected. '); });
How to run • Open a web browser which supports websocket • • chrome IE firefox safari • Server • make sure you have the new version nodejs • node-server. js
wireshark
wireshark • tcp. port == 8080 • start your websocket server • send from client, then close
HTTP upgrade to Websockwet
Client sends
Server Replies
Websocket Framing
Websocket is not perfect • Still Using TCP as transport layer protocol • Three way hand shaking • TCP flow control
Summary • HTTP 1. 0 -4. 0 vs 5. 0 • Web. Socket basic • Examples
- Slides: 37