websocket1

WebSocket

Using the most recent project to WebSocket, here we summarize the problems encountered and the methods used

What is at first introduced WebSocket

WebSocket is a network transport layer protocol, can be full duplex communication over a single TCP connection,
the application layer of the OSI model, the server allows WebSocket actively push the data to the client. Browser arms and I just need to complete a handshake, you can create a persistent connection between the two, and two-way data transmission.

Why use WebSocket (WebSocket What are the advantages to traditional HTTP)

  • Client and server only establish a TCP connection, you can use fewer connections
  • The server may push data to the client, the HTTP request response pattern than the more flexible, more efficient
  • More lightweight protocol header, reducing the amount of data transferred

WebSocket handshake

When a client establishes a connection, initiated by HTTP request packets

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

Differentiated portion HTTP request protocol:

Upgrade: websocket
Connection: Upgrade

These two fields representing a request for the upgrade server WebSocket.

Sec-WebSocket-Key Safety check:

Sec-WebSocket-Key value is randomly generated Base64 encoded string. After the server receives the character string which is connected 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, line into dGhlIHNhbXBsZSBub25jZQ == 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, and compute the result sha1 secure hash algorithm, performing Base64 encoding and finally returned to the client.

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

The above two fields specify the sub-protocol and version number

After the server processed the request, the response message as follows:

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

Status code 101 indicates handover protocol, the application layer protocol WebSocket update protocol, and application of a new protocol on the current socket

Sec-WebSocket-Accep:

It represents server-based string Sec-WebSocket-Key generated

Sec-WebSocket-Protocol:

It represents the end-use agreement

Client code

let ws = new WebSocket('ws://192.168.10.40:3000/')
      ws.onopen = mes=>{
        console.log(mes,'aaa')
  }

Server code

const net = require('net');
const crypto = require('crypto');
const wsGUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
net.createServer(function(socket) {
    socket.on('data', function(buffer) {
        // data 是buffer需要转化
        const data = buffer.toString(),
            key = getWebSocketKey(data),
            acceptKey = crypto.createHash('sha1').update(key + wsGUID).digest('base64'),
            headers = [
                'HTTP/1.1 101 Switching Protocols',
                'Upgrade: websocket',
                'Connection: Upgrade',
                'Sec-WebSocket-Accept: ' + acceptKey
                ];
        socket.write(headers.concat('','').join('\r\n'));
    })
}).listen(3000)

function getWebSocketKey(dataStr) {
    var match = dataStr.match(/Sec\-WebSocket\-Key:\s(.+)\r\n/);
    if (match) {
        return match[1];
    }
}

Client API

1.websocket Constructor

WebSocket object as a constructor to create a new instance WebSocket.

var ws = new WebSocket('ws://localhost:8080');

After executing the above statement, the client will connect to the server. The picture below is a list of all the properties and methods of an object instance

2.webSocket.readyState

readyState property returns an instance of the object's current state, there are four.

console.log(ws.readyState) // 我们可以输入看当前是什么状态
  • CONNECTING: 0, it means is connected.
  • OPEN: A value of 1 indicates a successful connection, the communication can be.
  • CLOSING: value 2, it indicates that the connection is closed.
  • CLOSED: a value of 3, indicates that the connection has been closed, or open the connection fails.

3.webSocket.onopen

onopen object attribute instance, specify a callback function for the successful connection.

ws.onopen = function () {
  ws.send('Hello Server!');
}

If you want to specify multiple callback functions, you can use addEventListenerthe method.

ws.addEventListener('open', function (event) {
  ws.send('Hello Server!');
});

4.webSocket.onclose

onclose object attribute instance, the callback function for the designated connection is closed.

ws.onclose = function(event) {
  var code = event.code;
  var reason = event.reason;
  var wasClean = event.wasClean;
  // handle close event
};

5.webSocket.onmessage

onmessage object attribute instance, specify a callback function for the received server data

ws.onmessage = function(event) {
  var data = event.data;
  // 处理数据
};

ws.addEventListener("message", function(event) {
  var data = event.data;
  // 处理数据
});

We can use this callback function to handle the returned data is equivalent to what we usually use axios successful data then return method

6.webSocket.send()

Examples of objects send () method for transmitting data to the server

ws.send('your message');

7.webSocket.bufferedAmount

bufferedAmount object attribute instance, it indicates how many bytes of binary data is not sent. It can be used to determine whether to end the transmission.

var data = new ArrayBuffer(10000000);
socket.send(data);

if (socket.bufferedAmount === 0) {
  // 发送完毕
} else {
  // 发送还没结束
}

8.webSocket.onerror

onerror property of an object instance, the callback function for the specified error.

socket.onerror = function(event) {
  // handle error event
};

socket.addEventListener("error", function(event) {
  // handle error event
});

Complete example

Server

import userInfoModel from '../model/userinfo';
import addendanceInfoModel from '../model/addentance';
import Websocket from 'ws';
import * as http from 'http';
const wss = new Websocket.Server({port: 3004});
wss.on('connection',function(ws:Websocket,req:http.IncomingMessage) {
    ws.on('message',async function(){
        try{
            // 获取基本数据
            const userData = await userInfoModel.find();
            ws.send(JSON.stringify(userData));
            // 获取出勤数据
            const addendanceData = await addendanceInfoModel.find();
            ws.send(JSON.stringify(addendanceData))
        }catch(err){
            ws.close()
        }
    })
})

The front websocket

// Ws 封装一系列websock方法
// getInstance   获取当前类的实例
// initConnect   初始化连接,返回promise,连接成功resolve,失败reject
// send   发送数据,包括断开重新连接
export default class Ws{
    constructor(){
        // 初始化连接
        this.initConnect() 
    }
    static getInstance() {
        if(!this.instance){
            this.instance = new Ws()
        }
        return this.instance;
    }   
    initConnect(){
        // 创建ws实例
        return new Promise((resolve,reject)=>{
            this.ws = new WebSocket('ws://192.168.10.40:3004/');
            this.ws.onmessage = event => this.message(JSON.parse(event.data));
            this.ws.onopen = event => resolve(event);
            this.ws.onclose = event => reject(event);
        })
    }
    async send(data){
        // 如果为连接断开就重新连接
        if(this.ws.readyState == 3 ){
            // 初始化连接
            await this.initConnect();
            // 连接成功发送消息
            data && this.ws.send(JSON.stringify(data))
        }else{
            // 发送消息
            data && this.ws.send(JSON.stringify(data))
        }
    }
    close() {
        if(this.ws.readyState == 3){
            return;
        } 
        this.ws.close();
    }
}

A front end assembly portion

<script>
import Ws from '@/assets/websocket.js';
export default {
  name: 'HelloWorld',
  mounted() {
    this.ws = Ws.getInstance();
    this.ws.message = this.onmessage;
  },
  methods:{
    onmessage(data) {
      console.log(data,'数据')
    },
    OnClick() {
      this.ws.send({})
    }
  }
}
</script>

websocket encountered pit

If the data is sent to the rear end of the front end, a rear end response time is too long, the read time may exceed the server, troubleshoot problems, and finally found a timeout nginx Agent

  proxy_read_timeout 60s;
  proxy_send_timeout 60s;

proxy_read_timeout 60s:

Set the read time-out from the back end, default 60s, he decided nginx will wait how long to get a response request, nginx will close the connection timeout

proxy_send_timeout 60s;

Sends a request to set the timeout upstream server, if the upstream server 60s no response is received, the connection is closed Nginx

We just need to find students to help us put the operation and maintenance agency prolonged, it would not have a timeout

We in the code can also be set to disconnect and reconnect

    initConnect(){
        // 创建ws实例
        return new Promise((resolve,reject)=>{
            this.ws = new WebSocket('ws://192.168.10.40:3004/');
            this.ws.onmessage = event => this.message(JSON.parse(event.data));
            this.ws.onopen = event => resolve(event);
            this.ws.onclose = event => reject(event);
        })
    }
    async send(data){
        // 如果为连接断开就重新连接
        if(this.ws.readyState == 3 ){
            // 初始化连接
            await this.initConnect();
            // 连接成功发送消息
            data && this.ws.send(JSON.stringify(data))
        }else{
            // 发送消息
            data && this.ws.send(JSON.stringify(data))
        }
    }

In the above code, the rear end of each transmission data to judge whether the current websocket connection state, when the state is 3 (disconnected), it is reconnected to the rear end of the data transmission connection is successful.

Guess you like

Origin www.cnblogs.com/mengxiangji/p/11720197.html