[Advanced Network] WebSocket Protocol

1. Application of Web real-time technology

Real-time Web technologies are of great significance in many application scenarios, they allow users to obtain the latest data and information immediately, thereby improving user experience. The following are some typical applications of real-time web technologies:

  1. Chat and Messaging: Live chat applications, corporate messaging software, and social networking platforms all require real-time technology to enable instant communication between users. Some well-known chat applications, such as WhatsApp, WeChat, Telegram, and Slack, etc., have adopted real-time technology.

  2. Online collaboration: Online document editing, real-time drawing boards, project management tools, etc. require multiple users to collaborate on documents or projects at the same time. Google Docs and Microsoft Office 365 are typical examples of online collaboration.

  3. Real-time news push: Applications such as news websites, blogs, stock quotes, and weather forecasts need to push the latest data and information to users in real time. Through real-time technology, users can receive the latest content without manually refreshing the page.

  4. Online gaming: Multiplayer online games, real-time strategy games, and virtual reality applications all require real-time technology to ensure player interaction. Real-time technology can reduce latency and improve game fluency and playability.

  5. Internet of Things (IoT): Real-time web technologies can be used to monitor and control IoT devices. For example, a smart home system can provide real-time feedback on the status of home devices, and users can control home appliances at any time.

  6. Real-time analysis: Real-time data analysis, data visualization and big data processing require real-time technology to support. For example, applications such as website access statistics, sales data analysis, and server performance monitoring need to display data in real time.

  7. Real-time audio and video communication: Voice calls, video conferencing and live broadcast applications require real-time technology to transmit audio and video data. These applications often use real-time communication technologies such as WebRTC.

  8. Real-time positioning and navigation: Location-based services, mapping applications, and traffic information systems require real-time technology to acquire and update location data. For example, applications such as Uber and Gaode map need to display the location of users and vehicles in real time.

Real-time Web technologies are widely used in many fields, and they provide users with a richer and more real-time network experience. In the future, with the popularization of technologies such as 5G and edge computing, real-time web technologies will be more commonly used in various scenarios.

2. Introduction to WebSocket protocol

The WebSocket protocol is a communication protocol based on TCP, which provides a full-duplex, low-latency communication method, enabling two-way real-time data exchange between the client and the server. The WebSocket protocol is designed to provide more efficient and real-time two-way communication between web browsers and web servers.

The WebSocket protocol is different from the HTTP protocol. It uses its own independent protocol identifier "ws" (unencrypted) or "wss" (encrypted), for example: ws://example.com or wss://example.com. The WebSocket protocol was originally proposed as a part of the HTML5 standard, and now it has been widely used in Web applications, online games, real-time communications and other fields.

2.1 How WebSocket works

  1. Establish a connection: First, the client will send an HTTP request to the server, which contains the "Upgrade" and "Connection" header fields, indicating that it wants to upgrade the connection to WebSocket. If the server agrees to the upgrade, it returns an HTTP response with status code 101, indicating that the connection has been upgraded.

  2. Data frame: After the WebSocket connection is established, the client and server can start sending and receiving data. Data is transferred in "frames" in WebSocket, and each frame contains an identifier, payload length, and payload data. An identifier is used to indicate the type of frame (such as text, binary data, or control frame).

  3. Control frame: There are some special control frames in the WebSocket protocol, which are used to manage the status of the connection. For example, the "Close" frame is used to notify the other party to close the connection, the "Ping" frame is used to detect whether the connection is still active, and the "Pong" frame is used as a response to the "Ping" frame.

  4. Closing the connection: When a client or server wishes to close a connection, they send a "close" frame. The party that receives a "close" frame should respond with a "close" frame, and then both parties can close the TCP connection. In some cases, the WebSocket connection may be disconnected unexpectedly due to network reasons or other problems, in which case the "close" frame will not be sent.

2.2 Advantages

  1. Two-way real-time communication: WebSocket provides full-duplex communication, allowing the client and server to send and receive data simultaneously, enabling real-time interaction.
  2. Low Latency: Compared with technologies such as HTTP-based polling or long polling, WebSocket can greatly reduce the latency of data exchange.
  3. Reduce network overhead: Since WebSocket can maintain a long connection after the connection is established, it can reduce the additional network overhead caused by frequently establishing and closing connections.
  4. Easy integration: WebSocket is compatible with existing web technologies (such as HTML, CSS, and JavaScript), so developers can easily integrate WebSocket without changing the existing web application architecture.

2.3. Usage scenarios

  1. Real-time news push: such as chat applications, news feeds, stock quotes, etc.
  2. Online games: such as multiplayer online games, real-time strategy games, etc.
  3. Instant collaboration: such as online document editing, real-time drawing board, etc.
  4. Internet of Things (IoT): WebSocket can be used to monitor and control IoT devices in real time.
  5. Other real-time applications: Any scenario that requires real-time data exchange can consider using WebSocket.

2.4 Implementation Details

  1. Security: For increased security, encrypted WebSocket connections (wss://) are available. Also, it is recommended to implement proper authentication and authorization strategies on the server side.
  2. Cross-domain issues: WebSocket allows cross-domain connections, but it should be noted that the server should check the "Origin" field in the request header to prevent malicious connections.
  3. Heartbeat detection: In order to ensure the reliability of the connection, "Ping" frames can be sent periodically for heartbeat detection, so as to deal with it in time when the connection is interrupted.
  4. Browser Compatibility: While most modern browsers support WebSocket, be aware that some older browsers may not. In this case, some libraries (such as Socket.IO) can be considered to provide automatic downgrade to other transports.

3. WebSocket server implementation

3.1 Client code (HTML & JavaScript)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket Client</title>
    <style>
        #output {
      
      
            border: 1px solid #ccc;
            padding: 10px;
            width: 400px;
            height: 200px;
            overflow-y: scroll;
        }
    </style>
</head>
<body>
    <h1>WebSocket Client</h1>
    <label for="serverAddress">Server address:</label>
    <input type="text" id="serverAddress" value="ws://localhost">
    <label for="serverPort">Port:</label>
    <input type="number" id="serverPort" value="3000">
    <button id="connectBtn">Connect</button>
    <div id="output"></div>
    <button id="clearBtn">Clear</button><br>
    <input type="text" id="message" placeholder="Type your message...">
    <button id="sendBtn">Send</button>

    <script>
        function getBrowserInfo() {
      
      
            return {
      
      
                userAgent: navigator.userAgent,
                language: navigator.language,
                platform: navigator.platform,
                vendor: navigator.vendor,
            };
        }

        let ws;
        const serverAddress = document.getElementById('serverAddress');
        const serverPort = document.getElementById('serverPort');
        const connectBtn = document.getElementById('connectBtn');
        const output = document.getElementById('output');
        const message = document.getElementById('message');
        const sendBtn = document.getElementById('sendBtn');
        const clearBtn = document.getElementById('clearBtn');

        clearBtn.addEventListener('click', () => {
      
      
            output.innerHTML = '';
        });

        function appendOutput(text) {
      
      
            output.innerHTML += `${ 
        text}<br>`;
            output.scrollTop = output.scrollHeight;
        }

        connectBtn.addEventListener('click', () => {
      
      
            const address = `${ 
        serverAddress.value}:${ 
        serverPort.value}`;
            ws = new WebSocket(address);
            connectBtn.disabled = true;

            ws.addEventListener('open', () => {
      
      
                appendOutput(`Connected to server at ${ 
        address}`);
                ws.send(JSON.stringify(getBrowserInfo()));
            });

            ws.addEventListener('message', (event) => {
      
      
                appendOutput(`Server: ${ 
        event.data}`);
            });

            ws.addEventListener('close', () => {
      
      
                appendOutput('Disconnected from server');
                connectBtn.disabled = false;
            });

            ws.addEventListener('error', (event) => {
      
      
                appendOutput('Error: ' + event.message);
            });
        });

        sendBtn.addEventListener('click', () => {
      
      
            if (ws && ws.readyState === WebSocket.OPEN) {
      
      
                ws.send(message.value);
                appendOutput(`You: ${ 
        message.value}`);
                message.value = '';
            } else {
      
      
                appendOutput('Please connect to the server first.');
            }
        });

        message.addEventListener('keyup', (event) => {
      
      
            if (event.key === 'Enter') {
      
      
                sendBtn.click();
            }
        });
    </script>
</body>
</html>

3.2 Server-side code (C++)

#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/beast/websocket.hpp>
#include <iostream>
#include <string>
#include <thread>
#include <nlohmann/json.hpp>

namespace beast = boost::beast;
namespace http = beast::http;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = net::ip::tcp;
using json = nlohmann::json;

constexpr auto DEFAULT_PORT = "3000";

void handleSession(websocket::stream<tcp::socket> ws) {
    
    
  try {
    
    
    ws.accept();
    auto remote_endpoint = ws.next_layer().socket().remote_endpoint();
    std::cout << "Connected to client: " << remote_endpoint << std::endl;

    for (;;) {
    
    
      beast::flat_buffer buffer;
      ws.read(buffer);

      auto message = beast::buffers_to_string(buffer.data());
      std::cout << "Received: " << message << std::endl;

      // Check if received message is browser information
      try {
    
    
        auto browser_info = json::parse(message);
        if (browser_info.contains("userAgent") && browser_info.contains("language") &&
            browser_info.contains("platform") && browser_info.contains("vendor")) {
    
    
          std::cout << "Browser Information:\n";
          std::cout << "  User Agent: " << browser_info["userAgent"].get<std::string>() << std::endl;
          std::cout << "  Language: " << browser_info["language"].get<std::string>() << std::endl;
          std::cout << "  Platform: " << browser_info["platform"].get<std::string>() << std::endl;
          std::cout << "  Vendor: " << browser_info["vendor"].get<std::string>() << std::endl;
          continue;
        }
      } catch (...) {
    
    
        // Not a valid JSON or not containing browser information
      }

      ws.text(ws.got_text());
      ws.write(buffer.data());
    }
  } catch (beast::system_error const &se) {
    
    
    if (se.code() != websocket::error::closed)
      std::cerr << "Error: " << se.code().message() << std::endl;
  } catch (std::exception const &e) {
    
    
    std::cerr << "Error: " << e.what() << std::endl;
  }
}

int main(int argc, char *argv[]) {
    
    
  try {
    
    
    auto const address = net::ip::make_address("0.0.0.0");
    auto const port = static_cast<unsigned short>(std::atoi(argc == 2 ? argv[1] : DEFAULT_PORT));

    net::io_context ioc{
    
    1};
    tcp::acceptor acceptor{
    
    ioc, {
    
    address, port}};
    std::cout << "WebSocket server is listening on " << address << ":" << port << std::endl;

    for (;;) {
    
    
      tcp::socket socket{
    
    ioc};
      acceptor.accept(socket);
      std::thread{
    
    handleSession, websocket::stream<tcp::socket>{
    
    std::move(socket)}}.detach();
    }
  } catch (std::exception const &e) {
    
    
    std::cerr << "Error: " << e.what() << std::endl;
    return EXIT_FAILURE;
  }
}

Note that the Boost.Beast library is used in the above code to implement WebSocket and the JSON library of nlohmann/json to process JSON data. The installation of the Boost library has been explained before. The installation of the nlohmann/json library is explained below:

  1. Install wget (if not already installed) with the following command:
sudo yum install wget
  1. Download the single-file version of the nlohmann/json library using wget:
wget https://github.com/nlohmann/json/releases/download/v3.10.4/json.hpp

Note: Make sure to download the version that is compatible with your code. In this example, I downloaded version 3.10.4. You can find other versions here .

  1. Create a directory containing the nlohmann/json header files:
sudo mkdir -p /usr/local/include/nlohmann
  1. Move the downloaded json.hpp file into the directory you just created:
sudo mv json.hpp /usr/local/include/nlohmann/

The nlohmann/json library is now installed on your CentOS 7.6 system. In C++ code, you can use it by including the following header file:

#include <nlohmann/json.hpp>

When compiling, make sure the linker can find the header files of the nlohmann/json library. This usually requires no extra compiler flags, but if you do, you may need to add -Iarguments to specify the path where the header files are installed. For example:

g++ your_code.cpp -o your_program -I/usr/local/include

3.3 Test results

Client:
insert image description here
Server:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_52665939/article/details/130498867