advanced topic

Ajax & WebSocket


- Oscar Tong / @oscartong

AJax


  • History of Communication
  • Introducing XHR
  • XHR Level 2
  • Server-side App Dev

history

Form > iframe > Flash/Silverlight > AJAX

introducing xhr

  • Asynchronous send HTTP/HTTPS request
  • Loads server response data back to script


How it works ?

  • new XMLHttpRequest()
  • onreadystatechange
  • open
  • send
  • abort

introducing xhr - example

//create a XHR instance
var request = new XMLHttpRequest();

//listen for readyStateChange event
request.onreadystatechange = function(e){
    if(request.readyState === 4 && request.status === 200){
        console.log(request.responseText);
    }
};

//send request
request.open('GET', 'http://www.example.com/foo', true);
request.send();

xhr level 2


  • Request timeout
  • FormData objects
  • Binary data
  • Monitor progress
  • Cross-Origin requests

xhr level 2 - timeout

//initiate a XMLHttpRequest and handle timeout situation
var xhr = new XMLHttpRequest();
xhr.open('GET', 'foo');
xhr.timeout = 3000;
xhr.onload = onLoad;
xhr.ontimeout = onTimeout;
xhr.send();

//timeout event handler
function onTimeout(event){
    var xhr = event.target;
    //set a higher timeout value and resend the request
    xhr.timeout = 6000;
    xhr.open('GET', 'foo');
    xhr.send();
}

xhr level 2 - formdata


//create a form and append data
var formdata = new FormData();
formdata.append('username', 'Oscar Tong');
formdata.append('id', 1234); //number 1234 is converted to string '1234'
formdata.append('file', someFileInput.files[0]);

//create a request and post formdata
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.foo.com/bar.php');
xhr.send(formdata);

xhr level 2 - binary data


var xhr = new XMLHttpRequest();
xhr.open('GET', 'foo');

//set responseType as arraybuffer to send/receive binary data
xhr.responseType = 'arraybuffer';
xhr.onload = function(){
    var arraybuffer = xhr.response; //not responseText
    ....
};
xhr.send();

xhr level 2 - progress

//handle progress and other level2 events
var xhr = new XMLHttpRequest();
xhr.addEventListener('progress', onProgress);
xhr.addEventListener('load', onComplete);
xhr.addEventListener('error', onError);
xhr.addEventListener('abort', onCanceled);

function onProgress(event){
    if(event.lengthComputable){
        console.log('percent complete:', event.loaded / event.total);
    }
    else{
        //total size is unknown yet
    }
}

function onComplete(event){ ... }
function onError(event){ ... }
function onCanceled(event){ ... }

xhr level 2 - cross origin

- How it works?

xhr level 2 - cross origin

- Client side
//CORS means Cross Origin Resource Sharing
function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if('withCredentials' in xhr){
        //check if the XMLHttpRequest object has a 'withCredentials' property
        //which only exists on XMLHttpRequest Level 2 object
        xhr.open(method, url, true);
    }
    else if(typeof XDomainRequest != 'undefined'){
        //otherwise check if XDomainRequest exists
        //XDomainRequest only exists in IE, it is IE's way of making CORS request
        xhr = new XDomainRequest();
        xhr.open(method, url);
    }
    else{
        //sorry, your browser does not supports CORS
        xhr = null;
    }
}

xhr level 2 - cross origin

- Server side
//creating and sending a CORS request
var xhr = createCORSRequest('GET''http://api.twitter.com/foo');
xhr.send();
HTTP Request:
GET /foo HTTP/1.1 Origin: http://www.example.com Host: http://api.twitter.com Accept-Language: en-US User-Agent: Mozilla/5.0 ... HTTP Response: ... Access-Control-Allow-Origin: http://www.example.com Access-Control-Allow-Credentials: true Acceee-Control-Expose-Headers: Foo,Bar Content-Type: text/html; charset=utf-8 ...

server-side app dev

- AppEngine(Python)

  • Simple XHR
  • Handle timeout
  • CORS

websocket


  • Introducting WebSocket
  • Client side WebSocket
  • Server side WebSocket

introducting websocket


  • bi-direction
  • full-duplex
  • over tcp

websocket - protocol

 

websocket - handshake

Client > Server
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Origin: http://example.com
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

Server > Client

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

websocket - handshake

  • Sec-WebSocket-Key
  • Sec-WebSocket-Accept
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'

Sec-WebSocket-Accept = base64( sha1( Sec-WebSocketKey + GUID ) )

websocket - frame

  0               1               2               3
  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
 +-+-+-+-+-------+-+-------------+------------------------------+
 |F|R|R|R| Opcode|M| Payload len |    Extended payload length   |
 |I|S|S|S|  (4)  |A|     (7)     |          (16 or 64)          |
 |N|V|V|V|       |S|             |  (if payload len == 126/127) |
 | |1|2|3|       |K|             |                              |
 +-+-+-+-+-------+-+-------------+------------------------------+
 |    Extended payload length continued, if payload len == 127  |
 +-------------------------------+------------------------------+
 |                               |Masking-key, if MASK set to 1 |
 +-------------------------------+------------------------------+
 |     Masking-key continued     |        Payload Data          |
 +-------------------------------+------------------------------+
 :                   Payload Data continued ...                 :
 +--------------------------------------------------------------+
 |                   Payload Data continued ...                 |
 +--------------------------------------------------------------+

websocket - frame

  • FIN (1bit): final fragment in a message
  • Opcode (4bits): interpretation of the payload
  • 0x0: continuation frame
  • 0x1: text frame
  • 0x2: binary frame
  • 0x3-7: reserved non-control frames
  • 0x8: connection close
  • ...
  • Mask (1bit): whether payload data is masked
  • Payload length (7bits / 7+16bits / 7+64bits)

websocket - text frame

  0               1               2               3
  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
 +-+-+-+-+-------+-+-------------+------------------------------+
 |F|R|R|R| Opcode|M| Payload len |    Extended payload length   |
 |I|S|S|S|  (4)  |A|     (7)     |          (16 or 64)          |
 |N|V|V|V|       |S|             |  (if payload len == 126/127) |
 | |1|2|3|       |K|             |                              |
 +-+-+-+-+-------+-+-------------+------------------------------+
 ...
 
 Text frame:
 +-+-+-+-+-------+-+-------------+-----------+
 |1|0|0|0|  0x1  |0|     11      |Hello World|
 +-+-+-+-+-------+-+-------------+-----------+

websocket - close

  0               1               2               3
  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
 +-+-+-+-+-------+-+-------------+------------------------------+
 |F|R|R|R| Opcode|M| Payload len |    Extended payload length   |
 |I|S|S|S|  (4)  |A|     (7)     |          (16 or 64)          |
 |N|V|V|V|       |S|             |  (if payload len == 126/127) |
 | |1|2|3|       |K|             |                              |
 +-+-+-+-+-------+-+-------------+------------------------------+
 ...
 
 Close frame:
 +-+-+-+-+-------+-+-------------+
 |1|0|0|0|  0x8  |0|      0      |
 +-+-+-+-+-------+-+-------------+

client-side websocket

//creating a WebSocket instance and try connect to the server
var socket = new WebSocket('ws://www.example.com/socketserver');

//open event is fired when WebSocket is connected
socket.onopen = function(event){
    socket.send('Hello Server. How are you?');
};

//message event is fire when message is received from server
socket.onmessage = function(event){
    console.log('Server said:', event.data);
};

...

//close the WebSocket connection
socket.close();

server-side websocket

- NodeJS

  • Upgrade HTTP to WebSocket
  • Handle messages
  • Close connection

tcp/udp raw socket


  • tcp client
  • udp client/server

Demo(Telnet Client)

THANKS


Q&A


communication_topics

By Oscar Tong

communication_topics

  • 6,404