The emergence of HTML5 marks the collective outbreak of various modern browsers in the post-Flash era. It is also a concentrated release of the technology gathered by various manufacturers who are wary of Adobe and want to change their way of life after years of fighting for themselves and finally reach a certain consensus. The so-called “H5 is a box, You can put anything in there.”

One of the notable and widely supported ones is WebSocket. This article will try to explain what problems it is used to solve and how it differs from the basics of battle-hardened “traditional” sockets.

I. Definition and origin

Look text and meaning, in the face of WebSocket this name, web without too much explanation, silly points not clear socket is also quite familiar; Whether there is a connection or not, it doesn’t hurt to know it first:

(1.1) Traditional Socket API

Socket usually refers to two connected ends in a TCP/IP network environment and a set of programming apis designed to facilitate such development

As shown in the picture, the literal meaning of the English word “socket” is “hole” or “socket”.

As a technical term, socket usually means the latter, like a perforated socket. It describes the IP addresses and ports at both ends of a communication link. It can be used to implement communication between different devices. Socket, TCP Socket are common names, Chinese general habitual translation ** “Socket”, “TCP Socket” **, etc.

. As for why “socket” is translated into “socket,” there are no shortage of curious programmers, and the scientific article can be found at the reference link at the bottom of this article.

Think of the server host as a room full of outlets, each with a number, some providing 220 volts ac, some providing landline phone signals, and some providing cable television programming. The client software plugs into the socket with different numbers to get different services

The floor at which the Socket API resides

The OSI model, as a conceptual model, was proposed by the International Organization for Standardization (ISO), a standard framework that attempts to connect various computers worldwide as a network. Familiar protocols such as HTTP and FTP work at the top Application Layer.

The **TCP/IP Protocol Suite ** abstracts the software communication process into four layers of abstraction, often seen as a simplified seven-layer OSI model. When multiple layers of protocols work together, they resemble the Stack in the data structure, so they are also called the TCP/IP Protocol Stack.

TCP alone refers to a connection-oriented transmission control protocol. After a TCP connection, the client and server can send and receive messages to each other. The connection persists until the client or server disconnects.

Socket is not a standard protocol, but the application layer and TCP/IP protocol family communication intermediate software abstraction layer, it is a group of interfaces, the basic position in the OSI model session layer (layer 5), is to facilitate you directly use the lower protocol (generally TCP or UDP) and an abstraction layer.

In the design pattern, the Socket is a facade pattern that hides the complex TCP/IP protocol family behind the Socket API. To the user, a simple set of interfaces is all that is needed, allowing the Socket to organize data to conform to the specified protocol

The first set of Socket apis was implemented in THE C language, which became the de facto standard for sockets.



Common Socket API implementation

Some language implementations

Traditional backend programming languages have Socket API encapsulation. Before HTML5, if you want to use pure front-end technology to implement the TCP Socket client, Java applets (java.net.Socket or java.net.DatagramSocket or java.net.MulticastSocket), Flash (flash.net.Socket or Flash.net.XMLSocket) or Silverlight(System.Net.Sockets).

Here is a basic example using a server/client implementation of PHP:


      
//server.php

set_time_limit(0);
$ip = '127.0.0.1';
$port = 1999;
// Create a Socket
$sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
// Bind the Socket address and port
$ret = socket_bind($sock,$ip,$port);
// Start listening for links
$ret = socket_listen($sock,4);

$count = 0; // Accept a maximum of a few requests before exiting
do {
	// Another Socket handles the communication
    if (($msgsock = socket_accept($sock)) >= 0) {        
        // Send to the client
        $msg ="server: HELLO CLIENTS! \n";
        if (socket_write($msgsock, $msg, strlen($msg))) {
        	echo "Send successful! \n";
        }
        // Get input from the client
        $buf = socket_read($msgsock,8192);
        
        $talkback = "Accept success! Content is: $buf \ n";
        echo $talkback;
        
        if(++$count >= 5) {break;
        };    
    }
    / / close the sockets
    socket_close($msgsock);
} while (true);
socket_close($sock);
echo "TCP connection closed OK\n";
? >
Copy the code

      
//client.php

error_reporting(E_ALL);
set_time_limit(0);
$port = 1999;
$ip = "127.0.0.1";

/ / create a Socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// Bind the Socket address and port
$result = socket_connect($socket, $ip, $port);
if ($result >= 0) echo "TCP connection OK \ n";

$in = "client: HELLO SERVER! \r\n";
if(socket_write($socket, $in, strlen($in))) {
    echo "Send successful! \n";
}
$out = ' ';
while($out = socket_read($socket, 8192)) {
    echo "Accept success! Content is:",$out;
}

socket_close($socket);
echo "TCP connection closed OK\n";
? >
Copy the code

(1.2) WebSocket protocol brought by HTML5

WebSockets provide real-time communication capability for both ends of C/S, allowing the server to actively send information to the client, is a new two-way data flow protocol different from HTTP

In short, the traditional TCP Socket is a relatively standardized set of apis, while the newer WebSocket is a networking protocol — two different things.

WebSocket is based on TCP protocol, so it was called TCPConnection in the early draft. Finally, it was renamed because it borrowed the meaning of the traditional Socket to communicate with both ends of the TCP network.

Socket to WebSocket is like Java and JavaScript lei Feng and Lei Feng Ta Zhang SAN and Zhang Sanfeng Zhou Jie and Jay Chou Peking University and Peking University Jade Bird India and Indonesia basically have no relationship... -- Lu Xun, "What I have not said"Copy the code

Problems to be solved

In HTTP/HTTPS based on request/response mode, if the real-time requirements are high, the client needs to constantly ask the server for data that is not available, which is unwieldy and uneconomical in all aspects.

In WebSocket’s full-duplex mode, which allows data to be transmitted in both directions at the same time, the client simply listens quietly and the server notifies it automatically when data is available.

A similar technology to WebSocket

In fact, when we talk about real-time two-way communication, we naturally think of several attempts over the years based on HTTP technology; It is based on these practices and problems in the previous work that WebSocket emerged. Let’s briefly review the relevant solutions and their limitations:

Polling (Polling)

Using methods such as setInterval(), the client keeps sending requests and getting responses. This approach is relatively simple and can solve the problem to some extent. However, the polling interval needs to be carefully considered. If the polling interval is too long, users cannot receive updated data in a timely manner. If the polling interval is too short, too many query requests will be made, which will increase the burden on the server.

Long Polling

This is an improvement over polling. After the client sends a request, the server blocks the request with while(true) until the response data is available, and the client receives the response before sending the next request.

This approach, called “Hanging GET”, “reverse Ajax” or “Comet”, looks a lot like a server push, but is still a slow response over HTTP; In the case of frequent data update, its efficiency is not better than general polling.

HTTP flows (Streaming)

With HTTP 1.1 and with transfer-encoding: chunked in the response header, the data sent from the server to the client can be split into multiple parts, kept open (while-true, sleep, etc.), and periodically flushed () chunked.

The client sends a HTTP connection, only in XHR. The readyState = = 3 state, use XHR. The responseText. The substring to obtain data at a time.

However, the data response can be delayed by middlemen such as proxy servers or firewalls, so you may need to detect this extra to switch to long polling.

SSE (Server-Sent Events)

The SSE specification is also an integral part of the HTML 5 specification. The content type of the server-side response is text/event-stream, and the EventSource object is used on the browser side to process the returned data.

Compared to WebSocket, SSE has the following disadvantages:

  • Does not support CORS
  • One-way channel, which can only be sent from the server to the browser
  • Browser compatibility is slightly poor

Where WebSocket comes in

Most traditional approaches waste bandwidth (HTTP heads are large) and consume server CPU (accepting requests without information). WebSocket greatly reduces the above consumption and is more suitable for the following scenarios:

  • Applications with high real-time requirements
  • The chat room
  • IoT (Internet of Things)
  • Online multiplayer

Compatibility is also satisfactory, if at all, in the rare cases where it is necessary to work with older browsers or where real-time requirements are significantly low.

The expansion of the HTTP

The URL of WebSocket connection starts with WS :// or WSS ://, and its encryption and cookie policies are basically the same as those of HTTP/HTTPS.

Application layer protocols, such as HTTP and WebSocket, are based on TCP to transmit data. These advanced protocols can be regarded as TCP encapsulation.

Under HTTP, the server can never send data to the client without the client making a request.

As for WebSocket, it must rely on HTTP protocol for a handshake, to comply with the specification of the browser; You can think of it as a complement and an upgrade to HTTP.

After the first HTTP request is made, all subsequent communications are two-way over the TCP channel. Therefore, although HTTP and WebSocket are both based on TCP, they are completely different communication methods.

Consider a typical WebSocket handshake request:

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Copy the code

The server responds:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Copy the code

The first of these is the Update and Connection request response headers, which indicate that the request and acknowledgement switch to the WebSocket protocol.

13 is a fixed version number;

The request header sec-websocket-key is the browser’s randomly generated Base64 encoding, appending a “magic string” fixed to 258eAFa5-E914-47DA-95CA-C5AB0DC85B11. The SHA-1 digest is computed and base-64 encoded, which is sec-websocket-accept in the response. ╮ (╯ del ╰) ╭

Implementation in the browser

The WebSocket object can be called directly from the browser and is defined as follows:


enum BinaryType { "blob"."arraybuffer" };
[Constructor(USVString url, optional (DOMString or sequence<DOMString>) protocols = []), Exposed=(Window,Worker)]
interface WebSocket : EventTarget {
  readonly attribute USVString url;

  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSING = 2;
  const unsigned short CLOSED = 3;
  readonly attribute unsigned short readyState;
  readonly attribute unsigned long long bufferedAmount;

  // networking
  attribute EventHandler onopen;
  attribute EventHandler onerror;
  attribute EventHandler onclose;
  readonly attribute DOMString extensions;
  readonly attribute DOMString protocol;
  void close([Clamp] optional unsigned short code, optional USVString reason);

  // messaging
  attribute EventHandler onmessage;
  attribute BinaryType binaryType;
  void send(USVString data);
  void send(Blob data);
  void send(ArrayBuffer data);
  void send(ArrayBufferView data);
};

Copy the code

It looks something like this:

var ws = new WebSocket('ws://www.xxx.com/some.php');
ws.send('xxx'); // Only strings can be sent at a time
ws.onmessage = function(event) {
	var data = event.data;
};
ws.onerror = function() {
	ws.close();
};
Copy the code

II. An instance of WebSocket for multi-user interaction

Imagine a user scenario, like an online card game, in which multiple people enter the same room and each person’s actions are broadcast to the others.

The following uses WebSocket to do a most basic verification prototype, so that each player knows other people’s entry, departure, out of the card, regret card, and even play to change the card and so on:

(2.1) Server-side implementation

We use nodejs + expressjs base server setup, and https://github.com/websockets/ws encapsulation library server-side logic to realize the WebSocket protocol:

// server.js

var express = require('express')
var ws = require('./ws')

var app = express()

app.get('/'.function (req, res) {
    res.sendFile(__dirname + '/ws.html');
})

app.listen(3000.function () {
  console.log('Example app listening on port 3000! ')})Copy the code
// ws.js

const { Server, OPEN } = require('ws');

const clients = []; //array of websocket clients
const cardsArr = []; //array of {cardId, count, title, ... }

let _lock = false;

const wss = new Server({port: 40510})
wss.on('connection'.function (ws) {

	const _cid = clients.push(ws) - 1;

	ws.on('message'.function (json) {

		const {
			act,
			cid,
			data
		} = JSON.parse(json);

		switch (act) {
			case 'client:join':
				_onCustomerJoin(ws, _cid);
				break;
			case 'client:leave':
				_onCustomerLeave(cid);
				break;
			case 'client:add': / / increase brand
				_onAddCard(cid, data);
				break;
			case 'client:update': / / modify
				_onUpdateCard(cid, data);
				break;
			case 'client:remove': / / remove card
				_onRemoveCard(cid, data);
				break;
			case 'client:win': / / order
				_onWin(cid);
				break;
			default:
				console.log('received: %s', act, cid)
				break; }}); });function _ensureLock(func) {
	return function() {
		if (_lock) return;
		_lock = true;
		const rtn = func.apply(null.arguments);
		_lock = false;
		return rtn;
	};
}

function _findCard(cardId) {
	const cidx = cardsArr.map(Card= >Card.cardId).indexOf(cardId);
	return cidx;
}

const _broadcast = (excludeId, msg, data=null) = >{
	clients.forEach( (client, cidx) = >{
		if (cidx === excludeId) return;
		if (client && client.readyState === OPEN) {
			client.send(JSON.stringify({
				act: 'server:broadcast'.msg: msg,
				data: data })); }}); };const _onCustomerJoin = (ws, cid) = >{
	ws.send(JSON.stringify({
		act: 'server:regist'.data: {
			cid: cid
		}
	}));
	_broadcast(cid, 'Players join:', {cid: cid});
};
const _onCustomerLeave = (cid) = >{
	clients[cid].terminate();
	clients.splice(cid, 1);
	_broadcast(cid, 'Player exit:', {cid: cid});
};
const _onAddCard = _ensureLock( (cid, data) = >{
	const d = _findCard(data.cardId);
	if(d ! = =- 1) {
		cardsArr.splice(d, 1);
	}
	cardsArr.push(data);
	_broadcast(- 1.'Player adds cards', {
		cid: cid,
		Card: data,
		cardsArr: cardsArr }); });const _onUpdateCard = _ensureLock( (cid, data) = >{
	const d = _findCard(data.cardId);
	if (d === - 1) return;
	cardsArr[d] = data;
	_broadcast(- 1.'The player has changed the cards', {
		cid: cid,
		Card: data,
		cardsArr: cardsArr }); });const _onRemoveCard = _ensureLock( (cid, data) = >{
	const d = _findCard(data.cardId);
	if (d === - 1) return;
	cardsArr.splice(d, 1);
	_broadcast(- 1.'The player removed the card', {
		cid: cid,
		Card: data,
		cardsArr: cardsArr }); });const _onWin = _ensureLock( (cid) = >{
	//do sth. here
	_broadcast(cid, 'The player has lost his cards.'); });Copy the code

(2.2) Client implementation

<h1></h1>
<div></div>

<button onclick="_add()">Out of the card</button>
<button onclick="_update()">The card</button>
<button onclick="_remove()">If brand</button>
<button onclick="_win()">Hu CARDS</button>
<button onclick="_leave()">leave</button>

<script>
    let cid = null; 

    const ws = new WebSocket('ws://localhost:40510');

    ws.onopen = function () {
        console.log('websocket is connected ... ');

        _send({
            act: 'client:join'
        });
    };

    ws.onmessage = function (ev) {
        
        const {
            act,
            msg,
            data
        } = JSON.parse(ev.data);

        switch(act) {
            case 'server:regist':
                cid = data.cid;
                console.log(`regist: cid is ${cid}`);
                document.querySelector('h1').innerHTML = 'I AM: ' + cid;
                break;
            case 'server:broadcast':
                console.log('Broadcast received from server:', msg, data);
                if (data && data.cardsArr) {
                    document.querySelector('div').innerHTML = JSON.stringify(
                        data.cardsArr, null.4
                    );
                }
                break;
            default:
                console.log(ev);
                break; }}function _send(json) {
        ws.send(JSON.stringify(json));
    }

    function _add() {
        _send({
            act: 'client:add'.cid: cid,
            data: {
                cardId: 111.count: 1.title: Red peach 'A'}})}function _update() {
        _send({
            act: 'client:update'.cid: cid,
            data: {
                cardId: 111.count: 2.title: 'spades 9'}})}function _remove() {
        _send({
            act: 'client:remove'.cid: cid,
            data: {
                cardId: 111}})}function _win() {
        _send({
            act: 'client:win'.cid: cid
        })
    }
    function _leave() {
        _send({
            act: 'client:leave'.cid: cid
        })
    }
</script>
Copy the code

(2.3) Operation effect

Player 0 joins:

Player 1 joins:

Player 1 plays:

Player 1 folds and quits:

III. To summarize

  • Traditional TCP sockets tend to refer to two connected ends in a TCP/IP network environment and a set of programming apis designed to facilitate such development
  • WebSockets provide real-time communication between C/S ends, allowing the server to proactively send information to the client
  • WebSockets are a part of the HTML 5 specification and a new two-way data flow protocol that is different from HTTP
  • WebSockets for full-duplex communication effectively improve the disadvantages of long polling and other methods before
  • WebSockets are suitable for real-time applications, chat rooms, multiplayer games, etc

IV. Reference materials

  • Why want to translation complete socket: https://www.bbsmax.com/A/kvJ3rDV9zg/
  • https://blog.zengrong.net/post/2199.html
  • http://www.cnblogs.com/thinksasa/archive/2013/02/26/2934206.html
  • https://coderanch.com/t/204527/java/Successful-Applet-Socket-Connection
  • https://www.zhihu.com/question/20215561
  • https://www.jianshu.com/p/42260a2575f8
  • https://www.jianshu.com/p/59b5594ffbb0
  • http://enterprisewebbook.com/ch8_websockets.html
  • https://medium.com/@dominik.t/what-are-web-sockets-what-about-rest-apis-b9c15fd72aac
  • https://medium.com/platform-engineer/web-api-design-35df8167460
  • https://www.websocket.org/quantum.html
  • https://blog.gtwang.org/web-development/websocket-protocol/
  • https://medium.com/kifi-engineering/websockets-vs-regular-sockets-b3b8e7ea0708
  • http://shouce.jb51.net/actionscript3.0/flash/net/Socket.html
  • https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/XMLSocket.html
  • https://github.com/theturtle32/AS3WebSocket
  • https://baike.baidu.com/item/socket/281150
  • The https://baike.baidu.com/item/TCP%2FIP protocol family
  • https://www.cnblogs.com/xuehaoyue/p/6639029.html
  • https://kotlintc.com/articles/4925
  • https://blog.csdn.net/future_todo/article/details/50097363
  • https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
  • http://lamb-mei.com/462/websocket-%E7%A5%9E%E5%A5%87%E5%AD%97%E4%B8%B2-258eafa5-e914-47da-95ca-c5ab0dc85b11/
  • https://kaazing.com/html5-websocket-security-is-strong/
  • https://www.asni.cn/2152

(end)

Long press the QR code or search fewelife to follow us