background
In a recent project, there was a requirement for lamp state data display. The requirement was to display the color and countdown of each group of lamps in real time. The technical aspect is to control the delay to be very low.
For real-time information acquisition, we generally have four schemes:
- Polling, the browser timer initiates an HTTP request
- Long polling (Comet), browser-initiated long polling supported by HTTP1.1
- Websocket, the browser and the back-end server establish a Websocket connection, duplex (bidirectional) communication
- Server-sent Events (SSE), a new FEATURE of HTML5 based on HTTP, Server push, half duplex communication model
Ps: Http2.0 has a server push is not real-time requirements of the solution, this feature is the server based on the client request, advance to return multiple responses, push additional resources to the client. If a request is sent from your home page, the server may respond with the home page content, logo, and style sheet because it knows the client will use those things. This not only reduces data transfer redundant steps, but also speeds up page response and improves user experience.
Flash-based socket implementations are phased out and out of consideration.
The following text version of the demo is a reference on zhihu user @ Ovear answer, recommend everyone to look at the original, by the way, take a look at the problem of other answer: www.zhihu.com/question/20…
polling
Polling is when the client periodically sends Ajax requests to the server, which immediately returns a response and closes the connection.
This is based on the “distributed, stateless, TCP-based request/response” HTTP protocol.
Text demo
Client: la la la, any new information (Request) Server: No (Response) Client: la la la, any new information (Request) server: no. (Response) Client: la la la, do you have any new information (Request) server: You are so annoying, no. (Response) Client: la la la, is there any new message (Request) server: ok la la, there is for you. (Response) Client: la la la, is there any new message (Request) server:... No... No... No (Response) ---- loopCopy the code
The demo code
<script type="text/javascript"> // Front-end Ajax calls the server continuously, called Ajax polling technology var getting = {url:'server.php',
dataType:'json',
success:function(res) { console.log(res); $.ajax(getting); // When the request takes too long (default: 60 seconds), the Ajax long polling error is called again:function(res){
$.ajax($getting); }}; $.ajax(getting); </script>Copy the code
Comet long polling, a hack technique
The client sends an Ajax request to the server, which holds the connection until it receives a new message and closes the connection. The client processes the response and then sends a new request to the server.
Comet can be implemented in two ways: Long polling based on Ajax and HTTP Streaming based on Iframe and HTMLfile.
Ajax long polling:
Iframe-based streams:
Embed a hidden IFrame in the page, then make the SRC attribute of the iframe point to a server address we requested, and for data update, we wrap the data update operation on the page into a JS function, passing the function name as an argument to the address.
After receiving the request, the server resolves the address to retrieve the parameter (the client js function call name), and returns the call to the client function whenever there is data update, and will fill in the returned content with the new data with the parameters of the JS function. For example, returning a string like “” means calling the client update function with data as the argument to update the client view.
Text demo
Client: la la la, do you have any new information, no words, and so on have to return it to me (Request) server:.. Wait till there is news. Response client: la la la la, do you have any new information, if not, wait for it to return to me (Request) -loopCopy the code
The demo code
<script type="text/javascript"> // Front-end Ajax calls the server continuously, called Ajax polling technology var getting = {url:'server.php',
dataType:'json',
success:function(res) { console.log(res); $.ajax(getting); // When the request takes too long (default: 60 seconds), the Ajax long polling error is called again:function(res){
$.ajax($getting); }}; $.ajax(getting); </script>Copy the code
websocket
Text demo
Client: la la la, I want to establish the Websocket protocol, the required service: chat, Websocket protocol version: 17 (HTTP Request) server: Yes, it has been upgraded to Websocket (HTTP Protocols Switched client) : Please push the information to me when you have it. Server: OK, I'll tell you sometime. Server: Balabalabalabala Server: Balabalabalabala server: hahahahahahaha client: Please push the information to me when you have it. Server side: Lmao ha ha ha ha ha haCopy the code
The demo code
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);
ws.close();
};
ws.onclose = function (evt) {
console.log("Connection closed.");
};
Copy the code
SSE(Server-Sent Event)
SSE means that the browser sends an HTTP request to the server, and the server continuously pushes a “message” to the browser in one direction. The format of the message is simple and fixed: the word “message” is prefixed with “data:” and then ends with “\n\n”.
SSE is an HTML5 standard that only uses HTTP to send asynchronous messages. Unlike WebSocket, SSE does not require the creation of a server socket on the back end.
Response. headers[” Content-type “] = “text/event-stream”.
Supported events are:
Onopen When a connection to the server is opened onMessage When a message is received onError when an error occursCopy the code
Eventsource.close () closes the connection.
Compatibility: developer.mozilla.org/zh-CN/docs/… Internet Explorer is not supported by all departments.
Text demo
SSE is a one-way channel, and only the server can send data to the browser. This is especially useful for applications where the client only needs to receive updates from the server.
Client: la la la, I want to set up SSE server: OK, sometime will tell you. Server: come here, have the news server: balabalabalabala server: ha ha ha ha ha mew: ahaha ha ha server: lol ha ha ha ha ha ha haCopy the code
The demo code
if(typeof (EventSource) ! = ="undefined") {
var source = new EventSource("server.php");
source.onopen = function () {
console.log("Connection to server opened.");
};
source.onmessage = function (event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
source.onerror = function () {
console.log("EventSource failed.");
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
Copy the code
choose
At present, we have accumulated rich experience in polling requests. However, polling, long polling is not enough for this demand. The main reasons are as follows: the indicator data is reported at a frequency of 500ms, which is very high. Polling is not suitable, and there are risks of request loss and asynchronous skip seconds. Moreover, polling in general has the problems of unnecessary requests, wasted bandwidth, and low efficiency. Therefore, you need to choose from SSE or WebSocket solutions. The pros and cons of SSE and WebSocket are compared as follows:
SSE | WebSocket | |
---|---|---|
Communication type | Half duplex (unidirectional) | Full duplex (bidirectional) |
Browser support | Currently not available in Microsoft browsers. | Available in all major browsers. |
Development workload | Small: Simply send an HTTP message containing a specific header. | Medium: TCP socket traffic needs to be established and maintained. A listener socket is also required on the server side. |
scalability | The weaker | Strong, support data two-way communication |
In order to better expandability later, we choose websocket scheme.
In-depth websocket
Simple to understand
WebSocket protocol was born in 2008 and became an international standard in 2011. All modern browsers already support it.
Its biggest characteristic is that the server can take the initiative to push information to the client, the client can also take the initiative to send information to the server, is a real two-way equal dialogue, belongs to a server push technology.
Features:
-
Based on TCP protocol, the implementation of the server side is relatively easy.
-
It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase uses HTTP protocol, so it is not easy to mask the handshake and can pass various HTTP proxy servers.
-
The data format is relatively light, with low performance overhead and high communication efficiency.
-
You can send text or binary data.
-
There are no same-origin restrictions, and clients can communicate with any server.
-
The protocol identifier is WS (or WSS if encrypted), and the server URL is the URL.
ws://example.com:80/some/path
Copy the code
Introduction to client implementation and API
Websocket is supported by all major browsers, including Internet Explorer.
- The constructor WebSocket(URL [, protocols]) returns a WebSocket object
- attribute
- Websocket. binaryType uses binary data types to connect to bloBs. (BLOb objects represent immutable, raw data file-like objects.) , arrayBuffer
- Websocket. bufferedAmount Read-only Number of bytes not sent to the server
- Websocket. extensions Extensions selected by the read-only server
- Websocket. onclose is used to specify the callback function after the connection is closed
- Websocket. onerror is used to specify the callback function if the connection fails
- Websocket. onMessage is used to specify the callback function when a message is received from the server
- Websocket. onopen is used to specify the callback function if the connection is successful
- Websocket. protocol Subordinate protocol selected by the read-only server
- Websocket. readyState Read only the current link state
- Websocket. url Indicates the absolute path of the read-only WebSocket
- methods
- Websocket.close ([code[, reason]]) closes the current link
- Websocket. send(data) Sends data to the server
Example browser client code:
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);
ws.close();
};
ws.onclose = function (evt) {
console.log("Connection closed.");
};
Copy the code
Server-side implementation
Almost all backend languages have corresponding implementation methods, which are well supported.
There are three common Node implementations.
- (including web sockets
- Socket.IO
- WebSocket-Node
Skip the code, directly to the above project in GitHub to view.
Nginx support
Add the following configuration to the HTTP and HTTPS domain names:
location /websocket {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
Copy the code
Nginx has supported WebSocket since version 1.3 and can do reverse proxy and load balancing for WebSocket applications.
WebSockets are affected by Nginx’s default proxy_read_timeout of 60 seconds. This means that if you have an application that uses WebSocket and doesn’t send any data for more than 60 seconds, you either need to increase the timeout or implement a ping message (heartbeat message) to stay in touch. The ping solution has the added benefit of finding out if the connection was accidentally closed.
Deep understanding of
What exactly is a Websocket?
Concept:
HTTP is an application protocol that runs on the TCP transport layer, while WebSocket is an application protocol that negotiates connections through HTTP and runs independently on the TCP transport layer.
WebSocket simply uses the HTTP protocol to make connection requests. WebSocket is a simplified version of the TCP transport sub-layer (actually WebSocket is also an application layer protocol).
WebSocket can persist connections because it runs on TCP. TCP is a long-connection protocol, so of course WebSocket can persist connections. The reason why HTTP is not a long connection is that the early DAYS of HTTP closed the Socket after each request was made and the response completed. However, after the addition of multiplexing KeepAlive protocol HTTP protocol has been able to achieve long connection, can deal with long connection transactions.
So, Websocket is a persistent protocol.
In particular:
WebSocket is not HTML5 stuff.
WebSocket is a protocol that belongs to IETF. The WebSocket API is a Web API owned by the W3C. The two specifications are published independently.
HTML5 in its broadest sense is a broad concept, a catch-all for a number of new apis that include the WebSocket API, not WebSocket. In simple terms, you can think of WebSocket as HTTP and the WebSocket API as Ajax.
Principle and operation mechanism
Wesocket protocol flow chart:
Websocket borrows the HTTP protocol for part of the handshake.
A typical Websocket HTTP handshake:
1. Request section
GET the ws: / / XXX. Xx. Xx. Xx: 8000 / v2x omp/websocket HTTP / 1.1 Host: XXX. Xx. Xx. Xx: 8000 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: http://xxx.xx.xx.xx:8000 Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36 Accept-encoding: gzip, deflate Accept-Language: zh-CN,zh; Q = 0.9 cookies: __guid = 120070472.2101968800548691200.1551342012289.0847; xx_xxow=_QP5elb46q2pqak9IgU_V0scW3xDh9Qm; monitor_count=1 Sec-WebSocket-Key: Uk07fY3CxNYoq2N5Fl9l1A== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bitsCopy the code
The main differences with the general HTTP protocol are:
(1)
Upgrade: websocket
Connection: Upgrade
Copy the code
This is the core of Websocket, tell Apache, Nginx and other servers: here is initiated by Websocket protocol, please use the corresponding backend to deal with.
(2)
Sec-WebSocket-Key: Uk07fY3CxNYoq2N5Fl9l1A==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Version: 13
Copy the code
Sec-websocket-key is a Base64 encode value that is randomly generated by the browser to validate the server for interaction.
Sec-websocket-version indicates the WebSocket Draft (protocol Version) used by the server to avoid compatibility problems due to different versions.
2. Response
The server responds with a successful Websocket setup.
HTTP/1.1 101 Switching Protocols Server: nginx Date: Tue, 02 Apr 2019 08:11:57 GMT Connection: Upgrade Upgrade: websocket Sec-WebSocket-Accept: khI5KCJzpRnpR8H2sOx+nnGCDAY= Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits=15Copy the code
At this point, HTTP has done all of its work — the connection handshake is successful, and it’s all Websocket protocol.
Websocket Frame transfer protocol:
Reference documentation
Developer.mozilla.org/zh-CN/docs/…
www.ruanyifeng.com/blog/2017/0…
www.zhihu.com/question/20…
Blog.51cto.com/kusorz/2058…
zhuanlan.zhihu.com/p/21595082