Don't understand websocket? This article allows you to thoroughly understand the principle of websocket

About websocket video analysis:

In-depth talk about websocket protocol, tcp subcontracting and sticky package solutions,
interview techniques of big companies, and websocket protocol usage scenarios and implementation schemes

First, let's look at the background of websocket. We know that the http series protocol is built on tcp. In theory, it can communicate in both directions. But before http1.1, the server did not implement the push function. Each time it is a client request and the server responds. Let's take a look at the development of HTTP protocol on request processing.

  1. In http1.0, the life cycle of an http request is that the client initiates the request, the server responds, and the connection is disconnected. But we know that the disadvantage of the tcp protocol is that it takes time for the three-way handshake, coupled with the slow start and other characteristics, if every http request is like this, the efficiency is very low.
  2. In http1.1, the long connection is enabled by default (the keep-alive header is set in the client request). After the server processes a request, it will not close the connection immediately, but will wait for a certain time. The connection is closed if there is no request. In this way, the browser can not only continuously send requests in a tcp connection (the server will also limit the request threshold that can be processed on a connection), but can even send many requests at a time. This is the pipeline technology of http1.1. But he also has a problem, because for a client based on the http protocol, although he can send a lot of requests, when a request comes back, he cannot tell which request belongs to. Therefore, the returned packets can only be returned in the requested order, which leads to another problem-Head-of-Link Blocking. And although http1.1 supports long connections, it does not support the ability of the server to push (push). If the server has data to give to the client, it can only wait for the client to fetch it (pull).
  3. Come to http2.0, not only server push is realized, but also technology such as frame (iframe) and stream (stream) are used to solve the problem of thread blocking. In a tcp connection, http2.0 can send multiple http requests at the same time. Each request is a stream, and a stream can be divided into many frames. With the tag number, the server can send back the packet at will. After the client receives it, it can reassemble it according to the tag.

The above are some developments of the http protocol about requests, and websocket provides another solution for server push. It is essentially another application layer protocol (websocket protocol) encapsulated on the tcp protocol. Because it is based on tcp, server-side push is naturally not a problem. However, in terms of implementation, he does not directly connect to a tcp connection, and then transmit data packets based on the websocket protocol on it. He involves a protocol upgrade (exchange) process. Let's look at this process.

1 The client sends a request for protocol upgrade. Add the following http header to the http request

Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: k1kbxGRqGIBD5Y/LdIFwGQ==
Sec-WebSocket-Version: 13
Upgrade: websocket

2 If the server supports the websocket protocol, it will return a 101 status code to indicate that it agrees to the protocol upgrade and supports various configurations (if the server does not support certain functions or versions, or tell the client that the client can send a protocol upgrade request again). The service will return the following http header (refer to the websocket protocol).

Connection: Upgrade
Sec-WebSocket-Accept: y73KZR4t+hqD6KKYbkx2tULfBsQ=
Upgrade: websocket

3 This completes the protocol upgrade. The subsequent data communication is based on the tcp connection and uses the data packet encapsulated by the websocket protocol.

Let's understand this process through wireshark. First we start a server (ip: 192.168.8.226).

var http = require('http');
var fs = require('fs');
const WebSocket = require('ws');
// 如果在浏览器控制台进行测试,可以不起http服务器
const server = http.createServer(options,function(req,res){
    
    
    res.end(fs.readFileSync(`${
    
    __dirname}/websocket.html`));
}).listen(11111);

const wss = new WebSocket.Server({
    
     server }); 
wss.on('connection', function connection(ws) {
    
    
  ws.on('message', function(message) {
    
    
    ws.send(message);
  });

  ws.send('get it');
});

[Article benefits] C/C++ Linux server architect learning materials plus group 812855908 (data including C/C++, Linux, golang technology, Nginx, ZeroMQ, MySQL, Redis, fastdfs, MongoDB, ZK, streaming media, CDN, P2P, K8S, Docker, TCP/IP, coroutine, DPDK, ffmpeg, etc.)
Insert picture description here

We can test directly in the browser console

var ws = new WebSocket("ws://192.168.8.226:11111");
// 连接上后执行
ws.send(11)

At this time, let's look at the wireshark package.

Insert picture description here

First look at the first three records, this is the data packet of the TCP three-way handshake. We all understand this, so we won't show it. Then look at the fourth record. After expansion as follows.
Insert picture description here

We saw that after the tcp connection was established, the browser sent an http request with several websocket data packets. Then look at the next one.

Insert picture description here

The service returned an agreement to upgrade agreement or exchange agreement. We can see from the server code that we push a get it string to the browser when establishing a connection. Continue to see the record above.

Insert picture description here

This is the websocket protocol-based data packet that the server pushes to the browser. For the specific meaning of each field, refer to the websocket protocol. Continue to look down a record is a tcp ack for the data packet pushed by the server. Finally, we can take a look at the last three records with keep-alive. This is the keep-alive of the tcp layer mentioned in the previous article. Because we have no data transmission, the tcp layer will send probe packets intermittently. We can look at the structure of the probe packet.

Insert picture description here

There is one byte of probe data. What if we send a data packet to the server at this time?

Insert picture description here

The three pieces of data on a white background are the data sent by the browser to the server and the data pushed back by the server. tcp ack. We found that when the server pushes to the browser, the browser sends an ack, but when the browser sends to the server, the server does not seem to return an ack. Let's see why. First we look at the package sent by the browser.

Insert picture description here

Look at the data packet that the server pushes to the browser.

Insert picture description here

We found that when the server (tcp) pushed the message, the ack was also brought. Instead of sending two tcp packets. This is the mechanism of tcp. TCP does not send an ack to every packet. It will accumulate acknowledgments (send ack) to reduce network packets, but it also needs to make sure to reply to ack as soon as possible, otherwise it will cause the client to trigger a timeout retransmission. When does tcp send confirmation? For example, when data needs to be sent, or no data packet is received for a certain period of time, or the number of accumulated confirmations reaches a threshold, etc. Now that we have studied tcp, we might as well study more. Let's take a look at what happens if the server is shut down at this time.

Insert picture description here

The server will send a reset packet to the browser, telling him that it needs to disconnect. Go on, what if the browser itself calls close to close the connection.

Insert picture description here

We see that websocket will first send a FIN packet to the server, and then the server will return a FIN packet, and then start the real four waved hands. And the first fin package waved four times was sent by the server.

Let's take a look at the secure version of websocket. We start an https server.

var https = require('https');
var fs = require('fs');
const WebSocket = require('ws');

var options = {
    
    
    key: fs.readFileSync('./server-key.pem'),
    ca: [fs.readFileSync('./ca-cert.pem')],
    cert: fs.readFileSync('./server-cert.pem')
};

const server = https.createServer(options,function(req,res){
    
    
    res.end(fs.readFileSync(`${
    
    __dirname}/websocket.html`));
}).listen(11111);

const wss = new WebSocket.Server({
    
     server });

wss.on('connection', function connection(ws) {
    
    
  ws.on('message', function(message) {
    
    
    ws.send(message);
  });
});

Then execute it in the browser console.

var ws = new WebSocket("wss://192.168.8.226:11111");
ws.sned(11);

Then take a look at wireshark.

Insert picture description here

First establish a tcp connection, and then establish a tls connection. The subsequent data communication can be carried out based on encryption. Do not repeat. We will analyze the tls protocol later.

After a series of analysis, we should have a better understanding of the websocket protocol, and finally talk about a point about websocket. We found that if there is no communication on the websocket connection, the time that the websocket connection is maintained depends on tcp. Because we found that the tcp layer will always send probe packets. After reaching the threshold, the connection will be disconnected. So if we want to maintain the websocket connection, we need to send heartbeat packets by ourselves, such as ping and pong.

Pay attention to the official account and share more Internet technology content you are interested in!Insert picture description here

Guess you like

Origin blog.csdn.net/qq_40989769/article/details/111316270