java network communication: Springboot integrates Websocket

Network communication

  • What is webSocket?
  • WebSocket principle
  • Springboot integrates websocket process

Three elements of network communication: IP address (ipv4, ipv6), port number (unique identification of the application), protocol (rules for connection and communication, commonly used: tcp, udp)

Community-House-Road

Socket is short for “socket” and is used to establish communication links between computers, allowing data to be transferred over these connections.

What is webSocket?

WebSocket is a protocol that enables full-duplex communication over a single TCP connection, allowing two-way real-time communication between clients and servers. WebSocket is part of the HTML5 standard and its main features include:

  1. Two-way communication: WebSocket allows the server to actively push messages to the client, and also allows the client to send messages to the server, realizing two-way communication.
  2. Persistent connection: Unlike the traditional HTTP request-response model, a WebSocket connection can be maintained after it is established without the need to establish a new connection for each message, reducing communication delays and overhead.
  3. Low latency: WebSocket has low communication latency and is suitable for applications that require real-time performance, such as online chat, real-time data monitoring, online games, etc.
  4. Cross-domain support: WebSocket supports cross-domain communication and can establish connections between servers with different domain names.
  5. Lightweight header: The header data of the WebSocket protocol is smaller, reducing communication overhead.

WebSocket principle

The WebSocket protocol is built on the HTTP protocol and is upgraded to a WebSocket connection through the HTTP request upgrade mechanism (Upgrade). The basic connection process is as follows:
The client initiates a WebSocket connection request and establishes a TCP connection with the server.

The server responds to the WebSocket handshake request, and the two parties reach an agreement to upgrade and complete the connection establishment.

Once a connection is established, the client and server can communicate bidirectionally via WebSocket messages.

The connection can remain open until one of the parties sends a request to close the connection.

A WebSocket connection is a persistent connection that uses a fixed socket address (ws:// or wss://) and port number (usually 80 or 443). WebSocket messages use a lightweight frame format that reduces communication overhead. This makes WebSocket suitable for applications that require real-time communication, such as online chat, real-time data updates, online games, etc.

In Java, the WebSocket library usually handles low-level details such as WebSocket handshake, message encoding and decoding, connection management, etc., so developers can focus on the logic of the application layer. The two-way communication model of the WebSocket protocol makes it an ideal choice for real-time communication applications. It is widely used in scenarios with high real-time requirements.

springboot integration websocket process

pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version> <!-- Use the correct version number -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springws</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springws</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>

Basic dependencies

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>5.3.12</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-websocket</artifactId>
            <version>9.0.55</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

</project>

System configuration

server.port=8080
#WebSocket
websocket.address=ws://localhost:8080

Profile

@Configuration
public class WebSocketConfig {<!-- -->

    @Value("${ws://localhost:8080}")
    private String websocketAddress;

    /**
     * Inject ServerEndpointExporter,
     * This bean will automatically register the Websocket endpoint declared using the @ServerEndpoint annotation
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {<!-- -->
        return new ServerEndpointExporter();
    }

}

Wbsocket operation class

package com.hs.websocket;

import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}") //Interface path ws://localhost:8087/webSocket/userId;
public class WebSocket {<!-- -->

    private Session session;
    private String userId;
    private static Map<String, Session> sessionPool = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {<!-- -->
        this.session = session;
        this.userId = userId;
        sessionPool.put(userId, session);
        log.info(" &#8203;``[oaicite:3]`` &#8203;There are new connections, the total number is: {}", sessionPool.size());
    }

    @OnClose
    public void onClose() {<!-- -->
        sessionPool.remove(userId);
        log.info(" &#8203;``[oaicite:2]`` &#8203;The connection was disconnected, the total number is: {}", sessionPool.size());
    }

    @OnMessage
    public void onMessage(String messageText) {<!-- -->
        log.info(" &#8203;``[oaicite:1]`` &#8203;Received client message: {}", messageText);
    }

    @OnError
    public void onError(Session session, Throwable error) {<!-- -->
        log.error("User error, reason: {}", error.getMessage());
    }

    public void sendAllMessage(String message) {<!-- -->
        log.info(" &#8203;``[oaicite:0]`` &#8203;Broadcast message: {}", message);
        sessionPool.values().forEach(this::sendMessage);
    }

    public void sendOneMessage(String targetUserId, String message) {<!-- -->
        Session session = sessionPool.get(targetUserId);
        if (session != null & amp; & amp; session.isOpen()) {<!-- -->
            sendMessage(session, message);
        }
    }

    public void sendMoreMessage(String[] targetUserIds, String message) {<!-- -->
        for (String targetUserId : targetUserIds) {<!-- -->
            Session session = sessionPool.get(targetUserId);
            if (session != null & amp; & amp; session.isOpen()) {<!-- -->
                sendMessage(session, message);
            }
        }
    }

    private void sendMessage(Session targetSession, String message) {<!-- -->
        try {<!-- -->
            targetSession.getAsyncRemote().sendText(message);
        } catch (IOException e) {<!-- -->
            log.error("Failed to send message: {}", e.getMessage());
        }
    }
}

Front-end testing

<!DOCTYPE HTML>
<html>
<head>
    <title>Test My WebSocket</title>
</head>


<body>
TestWebSocket
<input id="text" type="text"/>
<button onclick="send()">SEND MESSAGE</button>
<button onclick="closeWebSocket()">CLOSE</button>
<div id="message"></div>
</body>

<script type="text/javascript">
    var websocket = null;


    //Determine whether the current browser supports WebSocket
    if ('WebSocket' in window) {<!-- -->
        //Connect to WebSocket node
        websocket = new WebSocket("ws://localhost:8080/websocket/88");
    } else {<!-- -->
        alert('Not support websocket')
    }


    //Callback method for connection errors
    websocket.onerror = function () {<!-- -->
        setMessageInnerHTML("error");
    };


    //Callback method for successful connection establishment
    websocket.onopen = function (event) {<!-- -->
        setMessageInnerHTML("open");
    }


    //Callback method for receiving message
    websocket.onmessage = function (event) {<!-- -->
        setMessageInnerHTML(event.data);
    }


    //Callback method for connection closing
    websocket.onclose = function () {<!-- -->
        setMessageInnerHTML("close");
    }


    //Listen to the window closing event. When the window is closed, actively close the websocket connection to prevent the window from closing before the connection is disconnected. The server will throw an exception.
    window.onbeforeunload = function () {<!-- -->
        websocket.close();
    }


    //Display the message on the web page
    function setMessageInnerHTML(innerHTML) {<!-- -->
        document.getElementById('message').innerHTML + = innerHTML + '<br/>';
    }


    //Close the connection
    function closeWebSocket() {<!-- -->
        websocket.close();
    }


    //Send a message
    function send() {<!-- -->
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

postman test

Create new workspaces

Enter via ctrl + n

Conduct China Unicom test based on the following URL

ws://localhost:8080/websocket/88