1. Instant messaging on the Web

Web side instant messaging technology is simply to achieve such a function: the server side can immediately update or change the data to the client side, such as instant message push and other functions are achieved through this technology.

But on the Web, there are ways to implement instant messaging due to browser limitations. The main reason for this limitation is that most Web traffic is when the browser sends a request to the server and the server responds to complete a real-world update of the data.

There are four main ways to achieve instant messaging, they are: short polling, long polling (Comet), long connection (SSE), WebSocket.

  • They can be broadly divided into two categories. One is implemented on top of HTTP, including short polling, Comet, and SSE. The other is not HTTP
  • The underlying implementation is WebSocket. Here’s a look at each of the four polling methods, along with their pros and cons.

1. Ajax short polling

The basic idea of short polling is that the browser sends HTTP requests to the server at regular intervals, and the server responds directly to the request, regardless of whether there is any data update.

Ajax Comet – long polling

Comet refers to the fact that when a server receives a request from a client, it does not respond directly, but suspends the request and determines whether the server-side data has been updated. If there is an update, it responds, and if there is no data, it closes the connection after a certain time limit (set on the server side) is reached. This significantly reduces the number of unnecessary HTTP requests and saves resources in comparison. The disadvantage of long polling is that hanging connections can also lead to wasted resources

3,SSE

SSE is a new feature of HTML5, full name server-sentevents. It allows services to push data to clients. SSE is essentially different from the previous long polling and short polling, although both are based on HTTP protocol. The biggest feature of SSE is that it does not need the client to send a request. As long as the server data is updated, it can be immediately sent to the client.

The advantages of SSE are obvious, it does not need to establish or maintain a large number of requests sent from the client side to the server side, saving a lot of resources and improving application performance. The implementation of SSE is very simple, and does not need to rely on other plug-ins. (IE browser is not supported, one-way channel)

4, WebSocket

WebSocket protocol defined by HTML5, WebSocket is an independent protocol created on TCP. Different from the traditional HTTP protocol, this protocol can achieve full-duplex communication between the server and the client.

In simple terms, you first need to establish a connection between the client and server, which requires HTTP. Once the connection is established, the client and server are on equal footing and can send data to each other without distinction between request and response. It can better save server resources and bandwidth, and can be more real-time communication

Request details analysis:

The browser sends the server an HTTP GET request with a URL starting with ws://

Connection: Upgrade I want to Upgrade

Upgrade:websocket Upgrades client requests to the Websocket protocol.

The response header also contains Upgrade:websocket, indicating the Upgrade to the WebSocket protocol.

Response 101: Handshake successful, HTTP switched to Websocket, connection established, browser and server can send messages to each other at any time.

Sec-websocket-accept and sec-websocket-key are compatible, providing basic protection to reduce malicious and unexpected connections.

Sec-websocket-accept is calculated as follows:

The calculation formula is:

Spliced sec-websocket-key with 258eAFa5-E914-47DA-95CA-C5AB0DC85B11. The digest is computed by SHA1 and converted to a Base64 string. ToBase64 (SHA1 (SEC-websocket-key + 258eAFa5-E914-47DA-95CA-C5AB0DC85b11))Copy the code

Contrast:

For compatibility, short polling > Long polling > long SSE>WebSocket

For performance reasons, WebSocket> long connection SSE> Long polling > short polling

2,Webscoket support by browser

3. Websocket application scenarios

The way to determine if the work at hand requires WebSocket technology is simple:

  • Does your application allow multiple users to interact with each other?
  • Does your application show constantly changing data on the server side?

Here are some typical application scenarios:

  1. Co-working/editing

We live in a decentralized office era, and often need to edit the same document in different locations at the same time, such as Tencent online Office documents, programming files, etc.

  1. Social/Subscribe

For example, the real-time update reminder of wechat circle of friends, the red dot notification of “like” or “comment”, the dynamic reminder of QQ’s special attention, the real-time synchronization of chat information, the subscription notification of news client and so on.

  1. Multi-player games

Interactive efficiency is critical for online real-time multiplayer games, and you don’t want to pull the trigger and your opponent will have moved 10 seconds earlier.

  1. Stock Market Fund quotation

The world of finance is fast changing — almost every millisecond. Outdated information can only lead to loss. Our human brains can’t continue to process that much data at that rate, and we need algorithms to do that for us. When you have a dashboard to keep track of companies you’re interested in, you want to know what they’re worth at all times, not 10 seconds ago. Using WebSocket, you can stream updates to these data changes without waiting.

  1. Live sports broadcast

In the sports reporting experience, delay reduction is the most important point.

  1. Audio and video chat/video conference/online education

Using the WebSockets getUserMedia API and HTML5 audio and video elements is an obvious choice. The emergence of WebRTC is a logical combination of what I’ve outlined, and it looks promising, but it lacks the support of current browsers.

  1. Location-based applications

A growing number of developers are borrowing the GPS capabilities of mobile devices to implement their location-based web applications. For example, shared bikes, shared cars, Baidu Tianyan, GPS map services, real-time movement trajectory of epidemic surveillance targets, and trajectory analysis of athletes. Using WebSocket TCP links lets data fly.

4,Relationships among WebSocket, SockJs, and STOMP

SockJs

SockJS is a JavaScript library designed as an alternative to the WebSocket protocol that many browsers do not support. SockJS is a simulation of WebSocket technology. SockJS will try its best to correspond to WebSocket API, and will prefer WebSocket for connection. However, when the server or client does not support WebSocket, The system automatically selects the best of the XHR stream, XDR stream, iFrame event source, iFrame HTML file, XHR polling, XDR polling, iFrame XHR polling, and JSONP polling.

Stompjs

STOMP — Simple Text Oriented Message Protocol — message-oriented Simple Text Protocol.

SockJS provides an alternative to WebSocket. But in either case, this form of communication is too low-level for practical use. STOMP protocol: to add appropriate message semantics to the communication between browsers and servers.

The WebSocket protocol defines two types of messages (text and binary), but does not define message semantics. The protocol defines a mechanism for clients and servers to negotiate subprotocols (that is, higher-level messaging protocols) that can be used on websockets to define what types each message can be sent, what format it is, the content of each message, and so on. The use of subprotocols is optional, but in any case, the client and server need to agree on some protocol that defines the content of the message.

\

In short, WebSocket is the underlying protocol, SockJS is the alternative to WebSocket as well as the underlying protocol, and STOMP is the upper layer protocol based on WebSocket (SockJS).

1. HTTP takes care of the details of how a Web browser initiates a request and how a Web server responds to a request. Assuming that HTTP does not exist, web applications can only be written using TCP sockets.

2. Using WebSocket (SockJS) directly is similar to writing a Web application using TCP sockets, because without a high-level protocol, we need to define the semantics of messages sent between applications and ensure that both ends of the connection follow those semantics;

3. Just as HTTP adds a request-response model layer on TOP of TCP sockets, STOMP provides a frame-based line format layer on top of WebSocket to define message semantics;

Message format:

The connection

[the CONNECT the accept - version: 1.1, 1.0 heart - beat: 10000100 00]Copy the code

Send a message

[SEND
destination:/app/chat.addUser
content-length:36
{"sender":"tony","type":"JOIN"}]
Copy the code

Subscribe to news

[SUBSCRIBE
 id:sub-0
 destination:/topic/public
 "]
Copy the code

Server broadcast message

[MESSAGE destination:/topic/public content-type:application/json; charset=UTF-8 subscription:sub-0 message-id:axsspnqm-15 content-length:67 {"type":"JOIN","content":null,"sender":"tony","receiver":null}]Copy the code

5, combat:

1. Server

The Spring-Messaging and Spring-WebSocket modules provide WebSocket-enabled STOMP, and once you have these dependencies, you can expose STOMP endpoints via WebSocket using SockJS Fallback

To set the webSocket configuration:

  1. @ EnableWebSocketMessageBroker: for enabling our WebSocket server.
  2. We implemented WebSocketMessageBrokerConfigurer interface, and implements the method of them.
  1. EndpointSang: We register a WebSocket endpoint that the client will use to connect to our WebSocket server.
  2. WithSockJS () : is used to enable backup options for browsers that do not support Websocket, using SockJS.
  1. StompEndpointRegistry: comes from the Spring framework STOMP implementation. STOMP stands for simple text-oriented messaging protocol. It is a messaging protocol that defines the format and rules for data exchange. Why do we need this? Because WebSocket is just a communication protocol. It does not define things like how to send messages only to users who subscribe to a particular topic, or how to send messages to a particular user. We need STOMP to implement these functions.
  2. In the configureMessageBroker method, we configure a message broker that routes messages from one client to another.

Messages starting with “/app” should be routed to the message handling method (which will be defined later).

Messages starting with “/topic” should be routed to the message broker. The message broker broadcasts messages to all connected clients that subscribe to a particular topic.

  1. In the following example, we use an in-memory message broker.
package com.springbootwebsocket.conf; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; /** * @description: TODO * @param: * @return: * @author: sy * @date: 2021/9/24 * / @ Configuration @ EnableWebSocketMessageBroker / / is used to enable our child under the WebSocket server protocol stomp to transmit messages based on agent (MessageBroker), The controller supports the use of @ MessageMapping public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {/ * * * We register a WebSocket endpoint, Override public void registerStompEndpoints(StompEndpointRegistry Registry) { The client connects through this breakpoint, allows socketJs access, Allow cross-domain / / on a web page, we can through this link / / http://localhost:8080/endpointSang / / and server connection registry. AddEndpoint ("/endpointSang ") / /. AddInterceptors (new HttpSessionHandshakeInterceptor ()). SetAllowedOrigins (" * ") / / allow cross-domain Settings. WithSockJS (); // Use SockJS} /** * to define the message proxy, */ @Override public void configureMessageBroker(MessageBrokerRegistry Config) {// Start with a simple message broker based on memory, accept the message users must begin with the path to receive the message config. EnableSimpleBroker ("/user ", "/ topic", "/ queue"); / / the global news prefix (client active messaging prefix), starting with/app data will be @ MessageMapping interceptor into the method body config. SetApplicationDestinationPrefixes ("/app "); / / point-to-point prefix used subscription (client subscription path will show), is not set, the default is/user/config. SetUserDestinationPrefix ("/user "); }}Copy the code

Create controllers to receive and send messages

Annotated @sendto and @Sendtouser are convenient but not very flexible

SimpMessagingTemplate has two push methods

convertAndSend(destination, payload); // Broadcast the message to a specific subscription path, like @sendto

convertAndSendToUser(user, destination, payload); // Push the message to a fixed subscriber subscription path, like @sendtouser

 @MessageMapping("/chat.sendMessage")
    @SendTo("/topic/public")
    public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {
        return chatMessage;
    }
    @MessageMapping("/chat.sendMessageToSingle")
    public void point(@Payload ChatMessage chatMessage) {
        log.info(chatMessage.getSender() + "--to--" + chatMessage.getReceiver());
        messagingTemplate.convertAndSendToUser(chatMessage.getReceiver(), "/queue/points", chatMessage);
    }
Copy the code

Add WebSocket event listener, broadcast user in and out, etc

public class WebSocketEventListener { @Autowired private SimpMessageSendingOperations messagingTemplate; @EventListener public void handleWebSocketConnectListener(SessionConnectedEvent event) { log.info("Received a new web socket connection"); } /** * is used to extract the user name from the Websocket session and broadcast the user exit event to all connected clients. */ @EventListener public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) { StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage()); String username = (String) headerAccessor.getSessionAttributes().get("username"); if(username ! = null) { log.info("User Disconnected : " + username); ChatMessage chatMessage = new ChatMessage(); chatMessage.setType(ChatMessage.MessageType.LEAVE); chatMessage.setSender(username); messagingTemplate.convertAndSend("/topic/public", chatMessage); }}Copy the code

2. Client

Introduce sockJS, stomp.js

< script SRC = "https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js" > < / script > < script SRC = "https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js" > < / script >Copy the code

Main code snippet:

function connect(event) {
    username = document.querySelector('#name').value.trim();

    if (username) {
        usernamePage.classList.add('hidden');
        chatPage.classList.remove('hidden');
        // receiverChatPage.classList.remove('hidden');
      
        var socket = new SockJS('/endpointSang');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, onConnected, onError);
    }
    event.preventDefault();
}
Copy the code
Function onConnected() {// Subscribe to the Public Topic as soon as the message reaches the subscribed Topic Stompclient. subscribe('/topic/public', onMessageReceived); stompClient.subscribe("/user/" + username + "/queue/points", onMessageSingleReceived); // Tell your username to the server stompClient.send("/app/chat.addUser", {}, JSON.stringify({sender: username, type: 'JOIN'}) ) userElement.textContent = username; connectingElement.classList.add('hidden'); }Copy the code
function sendMessage(event) {
    var messageContent = messageInput.value.trim();
    if (messageContent && stompClient) {
        var chatMessage = {
            sender: username,
            content: messageInput.value,
            type: 'CHAT'
        };
        stompClient.send("/app/chat.sendMessage", {}, JSON.stringify(chatMessage));
        messageInput.value = '';
    }
    event.preventDefault();
}
Copy the code

3. Implementation of communication in cluster mode

Websocket server needs to share information (Redis publish-subscribe model)

4. Frequently asked Questions

Sticking and unpacking problems