html-websocket

Introduction

WebSocket is a protocol providing full-duplex communication channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C.

WebSocket is designed to be implemented in web browsers and web servers, but it can be used by any client or server application. The WebSocket Protocol is an independent TCP-based protocol. Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request. The WebSocket protocol makes more interaction between a browser and a web server possible, facilitating the real-time data transfer from and to the server. This is made possible by providing a standardized way for the server to send content to the browser without being solicited by the client, and allowing for messages to be passed back and forth while keeping the connection open. In this way, a two-way (bi-directional) ongoing conversation can take place between a browser and the server. The communications are done over TCP port number 80, which is of benefit for those environments which block non-web Internet connections using a firewall. Similar two-way browser-server communications have been achieved in non-standardized ways using stopgap technologies such as Comet.

The WebSocket protocol specification defines ws and wss as two new uniform resource identifier (URI) schemes that are used for unencrypted and encrypted connections, respectively. Apart from the scheme name and fragment (# is not supported), the rest of the URI components are defined to use URI generic syntax.

WebSockets have to establish a connection to a server for data to flow. WebSockets only establish this connection once by HTTP Method, then all data is sent over this open WS protocol connection(ws as tcp payload). This means each event being sent takes very little resources from both the server and the client because a new connection never has to be established, and ws protocol is small.

It uses HTTP protocol to setup the connection, then switch to WS protocol for data transmission. actually when lower TCP connection is setup, client sends HTTP method to server, this is handled by websocket, hence the TCP connection is not closed, now client and server can send ws protocl for data transmission)(TCP+ws+payload)

So it’s very useful for server driver event, like to notify update to client(upgrade notification, stock price update etc)

Websocket event

When it comes to Web Socket events there are mainly four events. They are:

  • Open: acts as a handshake between client and server
  • Message: happens when the server sends some data. Messages can be plain text messages or binary data
  • Close: This marks the end of communication between server and client.
  • Error: When an error occurs, when a communication channel is opened then the error event occurs

Connectino setup
client request

1
2
3
4
5
6
7
8
9
10
11
12
13
GET / HTTP/1.1
Host: 192.168.43.135:12345
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: file://
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Sec-WebSocket-Key: bKdPyn3u98cTfZJSh4TNeQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

server response

1
2
3
4
5
6
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 4EaeSCkuOGBy+rjOSJSMV+VMoC0=
WebSocket-Origin: file://
WebSocket-Location: ws://192.168.43.135:12345/

Data transmission

websocket protocol is very short, its header only takes 8 bytes, two import ones

  • Opcode: playload type(text, binary)
  • Payload length: len of payload

server to client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Frame 7: 79 bytes on wire (632 bits), 79 bytes captured (632 bits)
Ethernet II, Src: Vmware_8a:3d:a7 (00:0c:29:8a:3d:a7), Dst: Vmware_c0:00:08 (00:50:56:c0:00:08)
Internet Protocol Version 4, Src: 192.168.43.135, Dst: 192.168.43.1
Transmission Control Protocol, Src Port: 12345, Dst Port: 50999, Seq: 205, Ack: 510, Len: 25
WebSocket
1... .... = Fin: True
.000 .... = Reserved: 0x0
.... 0001 = Opcode: Text (1)
0... .... = Mask: False
.001 0111 = Payload length: 23
Payload
JavaScript Object Notation
Line-based text data
Welcome, 192.168.43.1 !

client to server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Frame 9: 72 bytes on wire (576 bits), 72 bytes captured (576 bits)
Ethernet II, Src: Vmware_c0:00:08 (00:50:56:c0:00:08), Dst: Vmware_8a:3d:a7 (00:0c:29:8a:3d:a7)
Internet Protocol Version 4, Src: 192.168.43.1, Dst: 192.168.43.135
Transmission Control Protocol, Src Port: 50999, Dst Port: 12345, Seq: 510, Ack: 230, Len: 18
WebSocket
1... .... = Fin: True
.000 .... = Reserved: 0x0
.... 0001 = Opcode: Text (1)
1... .... = Mask: True
.000 1100 = Payload length: 12
Masking-Key: e17e8eb9
Masked payload
Payload
JavaScript Object Notation
Line-based text data
test message

Examples

client side in browser you can use other web socket client without browser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
};


// blob(binary)
ws.binaryType = "blob";
ws.onmessage = function(e) {
console.log(e.data.size);
};

ws.send('your message');

// ArrayBuffer
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
console.log(e.data.byteLength);
};

ws.onclose = function(evt) {
console.log("Connection closed.");
};

server side

1
2
3
4
5
6
7
8
9
10
11
12
13
// use websocket library to setup a server
import { WebSocketServer } from 'ws';

// when client
const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});

ws.send('something');
});