WebSocket is a protocol for full duplex communication over a single TCP connection provided by HTML5.

WebSocket makes the data interaction between the client and the server much simpler, allowing the server to actively push data to the client. In the WebSocket API, the browser and server only need to complete a handshake to create a persistent connection and two-way data transfer.

In the WebSocket API, the browser and the server just do a handshake, and then a fast channel is formed between the browser and the server. Data can be transferred directly between the two.

WebSocket is an advanced technology. It opens an interactive communication session between the user’s browser and the server. Using this API, you can send messages to the server and receive event-driven responses without having to poll the server for a response.

Ajax polling is now used by many web sites to implement push technology. Polling is an active HTTP request made by the browser to the server at a specific time interval, and the server then returns the latest data to the client’s browser. The disadvantages of this traditional mode are obvious, that is, the browser needs to make continuous requests to the server, and the HTTP request may contain a long header, in which only a small part of the data is really valid, obviously this will waste a lot of bandwidth and other resources.

The WebSocket protocol defined by HTML5 can better save server resources and bandwidth, and can communicate in more real time.

interface

WebSocket is used to connect to the main interface of the WebSocket server over which data can then be sent and received.

CloseEvent Event sent by the WebSocket object when the connection is closed.

MessageEvent Event that the WebSocket object dissolves when a message is received from the server.

WebSocket objects provide apis for creating and managing WebSocket connections and for sending and receiving data over that link.

readyState

Usually after instantiating a WebSocket object, the client connects to the server. However, the state of the connection is uncertain, so the readyState property is used to identify it. It has four values that correspond to different states:

  • CONNECTING: The value is 0, indicating that a connection is being established.
  • OPEN: the value is 1, indicating that the connection is successful and communication can be started.
  • CLOSING: The value is 2, indicating that the connection is CLOSING.
  • CLOSED: the value is 3, indicating that the connection is CLOSED or fails to be opened.

Usually there are some monitoring pages, and then real-time to query the data, if the use of polling is simply a particularly stupid method, in order to achieve the back-end push data, the front-end active access to the back-end data function, we experiment webSocket Demo. This is simply receiving and sending data.

There are several ways to implement webSocket connections, but they are all based on webSocket.

1. WebSocket (more detailed, simpler later)

1. The client

The WebSocket client application uses the WebSocket API to communicate with the WebSocket server through the WebSocket protocol.

import React, { Component } from 'react';
import { Card, Tabs, Button, Input } from 'antd';

const { TabPane } = Tabs;
const { Search } = Input;

class Index extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.ws = undefined;
  }

  handleGetServer = (a)= > {
    if ('WebSocket' in window) {
      console.log('Your browser supports webSocket! '.this.ws);
      if (this.ws ! = =undefined && this.ws ! = ='undefined') {
        console.log('Destroy or close close');
        this.ws.send('Client destroys socket');
        this.ws.close();
        delete this.ws;
      }

      / / const ws = new WebSocket (' http://10.1.70.160:3000/blog/websocket ');
      // Uncaught DOMException: Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.
      // This means to use the ws or WSS protocol instead of HTTP.
      this.ws = new WebSocket('ws: / / 10.1.70.160:3131');
      console.log(this.ws);

      this.ws.onopen = (a)= > {
        console.log('Server connection successful');
        this.ws.send('Server connection successful')}this.ws.onmessage = function (evt) {
        const received_msg = evt.data;
        console.log('Client receives message', received_msg);
      }

      this.ws.onclose = function() {
        console.log('Connection closed... '); }}else {
      alert('Your browser does not support WebScoket');
    }
  }

  handleSend = (value) = > {
    console.log(value, this.ws.readyState);
    this.ws.send(value);
  }

  render() {
    return (
      <Card bordered={false}>
        <Tabs defaultActiveKey="1" tabPosition="top">
          <TabPane tab="test" key="1">
            <Button onClick={()= >This.handlegetserver ()}> Connect to the server</Button>
            <br />
            <br />
            <Search
              placeholder="Input data"
              enterButton="Send"
              size="large"
              onSearch={value= > this.handleSend(value)}
              style={{ width: 300 }}
            />
          </TabPane>
        </Tabs>
      </Card>
    );
  }
}

export default Index;

Copy the code

1.1. First create a WebSocket object

To communicate using the WebSocket protocol, you need to create a WebSocket object, which will automatically attempt to establish a connection to the server.

The WebSocket constructor takes one required and one optional argument

new WebSocket(url: string, protocols: string|array<string>)
Copy the code

Url The URL to connect to, which should be the url to which the WebSocket server responds.

Protocols A protocol string or an array of protocol strings. These strings are used to specify subprotocols so that a server can implement multiple WebSocket protocols. The default is an empty string.

this.ws = new WebSocket('ws: / / 10.1.70.160:3131');
Copy the code

When returned, the this.ws. ReadyState parameter is CONNECTING, and the readyState becomes OPEN once the connection can send data.

When connecting to websockets, you need to use WS instead of HTTP and WSS instead of HTTPS.

Then listen onOpen, onClose and onMessage respectively to listen for the connection status and perform the corresponding operation.

1.2. Send data to the server

Once the connection is open, you can send data to the server. Use the WebSocket object send() method for each message to be sent:

this.ws.send('Server connection successful');
Copy the code

You can also send data as a string, Bolb, or ArrayBuffer

Since connection establishment is asynchronous and prone to failure, there is no guarantee that the send() method will succeed when the WebSocket object is first created. We can send data as soon as we can confirm that the connection has been established by registering the onOpen event handler:

this.ws.onopen = (a)= > {
  console.log('Server connection successful');
  this.ws.send('Server connection successful')}Copy the code

You can also send JSON objects to the server.

// The server sends text to all users
function sendText() {
  // Construct a MSG object that contains the data the server needs to process
  var msg = {
    type: "message".text: document.getElementById("text").value,
    id:   clientID,
    date: Date.now()
  };

  // Send the MSG object as a JSON string
  this.ws.send(JSON.stringify(msg));
  
  // Empty the text input element, ready to receive the next message.
  document.getElementById("text").value = "";
} 
Copy the code

1.3. Receive messages sent by the server

WebSockets are an event-based API, and when a message is received, a message is sent to the onMessage function. To start listening for incoming data, do the following:

this.ws.onmessage = function (evt) {
  const received_msg = evt.data;
  console.log('Client receives message', received_msg);
}
Copy the code

1.4. Shut down the service

When you no longer need a WebSocket connection, you can call the WebSocket close() method to close the connection.

2. The service side

A WebSocket server is a TCP application that listens for any port on the server that follows a particular protocol.

WebSocket servers can be written in many languages, such as C/C++, PHP, Python, server-side JavaScript(Node.js), etc. We are demonstrating the Node.js implementation

const http = require('http');
const express = require('express');
// Resume webSocket server through webSocket module
const webSocketServer = require('websocket').server;
const webSocketsServerPort = 3131;

const app = express();

app.get('/'.function(req, res, next) {
  res.send('Started successfully 1');
});

// Create an application server
const server = http.createServer(app);

// Start the Http service
server.listen(webSocketsServerPort, function() {
  console.log('ListEnding 3131');
});

//
wss = new webSocketServer({
  httpServer: server,
  autoAcceptConnections: true // Default: false
});
wss.on('connect'.function(ws){
  console.log('Server: Client already connected');
  ws.on('message'.function (message) {
    console.log(message);
    ws.send('The server received the message successfully...${message}`)
    setInterval(function(){
      ws.send('The server received the message successfully...The ${new Date().getTime()}`)},1000);
  })
})
wss.on('close'.function(ws){
  console.log('Server: Client initiated shutdown');
  // ws.on('message', function (message) {
  // console.log(message);
  // })
})
const clients = {};
// This code generates unique userid for everyuser.
const getUniqueID = (a)= > {
  const s4 = (a)= > Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  return s4() + s4() + The '-' + s4();
};


wss.on('request'.function(request) {
  console.log('Send request');
  const userID = getUniqueID();
  console.log((new Date()) + ' Recieved a new connection from origin ' + request.origin + '. ');
  const connection = request.accept(null, request.origin);
  clients[userID] = connection;
  console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(clients))
});


Copy the code

Pay attention to

2.1 autoAcceptConnections: true/false

The default value is false. You can manually set it to true, but it is not recommended

There is such a paragraph in the source code

// If this is true. websocket connections will be accepted // regardless of the path and protocol specified by the client. // The protocol accepted will be the first that was requested // by the client. Clients from any origin will be accepted. // This should  only be usedin the simplest of cases.  You should
// probably leave this set to 'false' and inspect the request
// object to make sure it's acceptable before accepting it.
Copy the code

Roughly translated,

If this field is true, webSocket connections do not consider the path and meaning specified by the client. When a request is received, the protocol is the first to receive it. Receive client segment requests from any source. AutoAcceptConnections is used only in the simplest cases.

In practice, it is best to set to “false” and then check to make sure the request is accepted before receiving the request object.

That’s where request comes in

2.2 to monitor the request

Do not set autoAccecptConnections or set it to false when using request

wsServer.on('request'.function(request) {
    if(! originIsAllowed(request.origin)) {// Make sure we only accept requests from an allowed origin
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    }
    
    var connection = request.accept('echo-protocol', request.origin);
    console.log((new Date()) + ' Connection accepted.');
    connection.on('message'.function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
            connection.sendUTF(message.utf8Data);
        }
        else if (message.type === 'binary') {
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes'); connection.sendBytes(message.binaryData); }}); connection.on('close'.function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    });
});
Copy the code

Onrequest is called when a client requests a connection. The request parameter contains the request information (IP, etc.)

2. Socket. IO the connection is successful

The client sends the information and the server receives it

  • The client
import React, { Component } from 'react';
import { Card, Tabs, Button, Input } from 'antd';
import io from 'socket.io-client';

const { TabPane } = Tabs;
const { Search } = Input;

class Index extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.ws = undefined;
  }

  handleGetServer = (a)= > {
    if ('WebSocket' in window) {
      console.log('Your browser supports webSocket! '.this.ws);
      if (this.ws ! = =undefined && this.ws ! = ='undefined') {
        console.log('Destroy or close close');
        this.ws.send('Client destroys socket');
        this.ws.close();
        delete this.ws;
      }

      / / const ws = new WebSocket (' http://10.1.70.160:3000/blog/websocket ');
      // Uncaught DOMException: Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.
      // This means to use the ws or WSS protocol instead of HTTP.
      / / this. Ws = new WebSocket (' ws: / / 10.1.70.160:3131 / home/index ');
      this.ws = io('ws: / / 10.1.70.160:3131');

      console.log(this.ws);
      this.ws.on('connect', () = > {console.log('Connection successful');
      })

      this.ws.on('disconnect', () = > {console.log('Client connection closed'); })}else {
      alert('Your browser does not support WebScoket');
    }
  }

  handleSend = (value) = > {
    console.log(value, this.ws);
    this.ws.send(value);
  }

  render() {
    return (
      <Card bordered={false}>
        <Tabs defaultActiveKey="1" tabPosition="top">
          <TabPane tab="test" key="1">
            <Button onClick={()= >This.handlegetserver ()}> Connect to the server</Button>
            <br />
            <br />
            <Search
              placeholder="Input data"
              enterButton="Send"
              size="large"
              onSearch={value= > this.handleSend(value)}
              style={{ width: 300 }}
            />
          </TabPane>
        </Tabs>
      </Card>
    );
  }
}

export default Index;

Copy the code
  • The service side
const app = require('express') ();const http = require('http').Server(app);
const io = require('socket.io')(http);

app.get('/'.function(req, res) {
  res.send('inc')
})

io.on('connection'.function (socket) {
  console.log('Server connected successfully')
  socket.on('message'.function(msg) {
    console.log('Message received', msg)
  })
  
  // Set a timer to send messages on the server and receive messages on the client
  setInterval(function() {
    socket.emit('message'.new Date().getTime())
  }, 10000);

  socket.on('disconnect'.function() {
    console.log('Connection closed')
  })
})
http.listen(3131.function () {
  console.log('listending 3131')})Copy the code

2.1 Start client and server projects respectively. React is used on the client and Express is used on the server

2.2 Client: Click the button “Connect to server” and send a message

You can then see that the client and server have implemented information passing to each other.

3. websocket — ws

The key to using WebSocket is server-side support so that it is possible to use WebSocket with a browser that supports WebSocket.

  • The client
import React, { Component } from 'react';
import { Card, Tabs, Button, Input } from 'antd';

const { TabPane } = Tabs;
const { Search } = Input;

class Index extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.ws = undefined;
  }

  handleGetServer = () => {
    if ('WebSocket' in window) {
      console.log('Your browser supports webSocket! ', this.ws);
      if(this.ws ! == undefined && this.ws ! = ='undefined') {
        console.log('Destroy or close close');
        this.ws.send('Client destroys socket');
        this.ws.close();
        delete this.ws;
      }

      // const ws = new WebSocket('http://10.1.70.160:3000/blog/websocket');
      // Uncaught DOMException: Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or 'wss'. 'http'is not allowed. // this. Ws = new WebSocket('Ws: / / 10.1.70.160:3131'); console.log(this.ws); this.ws.onopen = () => { console.log('Connecting to the server successfully'); this.ws.send('Connecting to the server successfully') } this.ws.onmessage = function (evt) { const received_msg = evt.data; console.log('Data accepted', received_msg); } this.ws.onclose = function() { console.log('Connection closed...'); } } else { alert('Your browser does not support WebScoket'); } } handleSend = (value) => { console.log(value, this.ws); this.ws.send(value); } render() { return ( 
       
        
         
          
         



this.handleSend(value)} style={{ width: 300 }} />
); } } export default Index;
Copy the code
  • The service side
// Import WebScoket module
const WebSocket = require('ws')
// Reference the Server class
const WebSocketServer = WebSocket.Server;
// instantiate port 3131
const wss = new WebSocketServer({ port: 3131 });
/ / the connection
wss.on('connection'.function (ws) {
  console.log('Server: Client connected');
  ws.on('message'.function (message) {
    // Prints the message that the client is listening to
    console.log(message);
  });
  // Emulated server sends message to client, comment out
  setInterval(function(){
    ws.send('Server sends message')},5000);
});
Copy the code

Error in connection establishment: net::ERR_CONNECTION_REFUSED

Index.js :27 WebSocket Connection to 'ws://10.1.70.160:3131/' Failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

Solution:

Read along while, the original is the wrong port number

2.2 Successful Results

The problem summary

1. Problem 1: Use WS or WSS instead of HTTP

Export const WebSocketTest = () => {if ('WebSocket' in window) {console.log(' Your browser supports WebSocket! '); Const ws = new WebSocket (' http://10.1.70.160:3000/blog/websocket '); Ws.onopen = function() {ws.send(' send data '); Console. log(' sending '); } ws.onmessage = function (evt) { const received_msg = evt.data; Console. log(' data received ', received_msg); } ws.onclost = function() {console.log(' Connection closed... '); }} else {alert(' Your browser does not support WebScoket'); }}Copy the code

webSocket.js:5 Uncaught DOMException: Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.

2. Error 2 Express uses POST to report 404

Error during WebSocket Handshake: Unexpected Response Code: 200 is reported when ws access is successful

Error during WebSocket handshake: Unexpected response code: 200

I looked it up online and said it was because of a server interceptor problem. Remember that WebSocket is HTTP based, and webSocket links are created using a handshake, which is a traditional HTTP request (as if the details vary from browser to browser, chrome is HTTP), so if the server has an interceptor, It will intercept the handshake message.

But look, it’s not like I’m looking

4. Error during WebSocket Handshake: Unexpected Response Code: 404

WebSocket connection to ‘ws://10.1.70.160:3131/’ failed: Error during WebSocket handshake: Unexpected response code: 404

The server code accesses OK alone

Client code:

import React, { Component } from 'react';
import { Card, Tabs, Button, Input } from 'antd';

const { TabPane } = Tabs;
const { Search } = Input;

class Index extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.ws = undefined;
  }

  handleGetServer = () => {
    if ('WebSocket' in window) {
      console.log('Your browser supports webSocket! ', this.ws);
      if(this.ws ! == undefined && this.ws ! = ='undefined') {
        console.log('Destroy or close close');
        this.ws.send('Client destroys socket');
        this.ws.close();
        delete this.ws;
      }

      // const ws = new WebSocket('http://10.1.70.160:3000/blog/websocket');
      // Uncaught DOMException: Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or 'wss'. 'http'is not allowed. // this. Ws = new WebSocket('Ws: / / 10.1.70.160:3131'); console.log(this.ws); this.ws.onopen = () => { console.log('Connecting to the server successfully'); this.ws.send('Connecting to the server successfully') } this.ws.onmessage = function (evt) { const received_msg = evt.data; console.log('The client receives the information', received_msg); } this.ws.onclose = function() { console.log('Connection closed...'); } } else { alert('Your browser does not support WebScoket'); } } handleSend = (value) => { console.log(value, this.ws.readyState); this.ws.send(value); } render() { return ( 
       
        
         
          
         



this.handleSend(value)} style={{ width: 300 }} />
); } } export default Index;
Copy the code
  • The service side
const http = require('http');
const express = require('express');
const webSocketServer = require('websocket').server;
const webSocketsServerPort = 3131;

const app = express();

app.get('/'.function(req, res, next) {
  res.send('Started successfully');
})

const server = http.createServer(app);

server.listen(webSocketsServerPort, function() {
  console.log('listending 3131');
});

wss = new webSocketServer({
  httpServer: server,
});
wss.on('connect'.function(ws){
  console.log('Server: Client already connected');
  ws.on('message'.function (message) {
    console.log(message); })})Copy the code

Problem: Because autoAcceptConnections: true is not configured or request is not listened on

5. index.js:31 WebSocket connection to ‘ws://10.1.70.160:3131/’ failed: Connection closed before receiving a handshake response

const app = require('express') ();const http = require('http').Server(app);
const io = require('socket.io')(http);

app.get('/'.function(req, res) {
  res.send('inc')
})

io.on('connection'.function (socket) {
  console.log('connect')
  socket.on('message'.function(msg) {
    console.log(msg)
  })
  
  socket.emit('message'.'hello')
  
  socket.on('disconnect'.function() {
    console.log('disconnect')
  })
})
http.listen(3131.function () {
  console.log('listending 3131')})Copy the code

IO: socket. IO: socket. IO: socket