WebSocket建立网络连接——小案例

发布于:2024-05-10 ⋅ 阅读:(32) ⋅ 点赞:(0)

WebSocket是一种实现全双工通信的网络技术标准,它允许在用户的浏览器和服务器之间进行持久的、双向的通信。以下是对WebSocket的具体介绍:

  1. 实时性:与传统HTTP请求相比,WebSocket提供了更高效的实时数据交换方式。一旦建立连接,客户端与服务端可以同时相互发送信息,而不需要像HTTP那样每次请求都要重新建立连接。
  2. 持久连接:WebSocket建立在TCP协议之上,它使用一次“握手”来建立连接,此后便可以在客户端和服务器之间保持一个持久的连接状态,直到其中一方主动关闭连接。
  3. 低延迟:由于WebSocket支持长连接和双向通信,它可以显著减少网络延迟,尤其适用于需要快速响应的场景,例如在线游戏、实时通知等。
  4. 轻量级:虽然WebSocket基于HTTP协议,但它有自己的专门协议,这使得它在传输效率上更高,头部信息更小,减少了额外的数据传输开销。
  5. 兼容性:WebSocket协议得到了现代浏览器的广泛支持,并且由W3C定为标准。同时,它也通过RFC 6455和RFC 7936被IETF确定为标准。
  6. 适用场景:WebSocket特别适用于那些需要服务器主动向客户端推送数据的应用场景,如聊天室、实时监控图表更新展示等。

首先创建客户端WebSocket:

 WebSocketClient.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WS_Client</title>
</head>
<body>
<input id="msg" type="text">
<button onclick="send()">发送消息</button>
</body>
<script>
    //连接WebSocket 服务器
    const clientId = Math.random().toString(36).substr(2);
    const websocket = new WebSocket("ws://localhost:8080/ws/" + clientId);

    //监听连接建立成功
    websocket.onopen = function (){
        console.log("WebSocket建立连接成功……")
    }

    //监听收到服务端消息
    websocket.onmessage = function (event){
        console.log(event.data);
    }

    //发送消息
    function send(){
        websocket.send(document.getElementById('msg').value);
    }

    //监听窗口关闭事件,当窗口关闭时主动去关闭webSocket连接
    window.onbeforeunload = function (){
        websocket.close();
    }
</script>
</html>

现在编写服务端WebSocketServe:

引入相关依赖:

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

编写WebSocketServer服务端:

package net.wanho.webSocket;

import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Component
@ServerEndpoint("/ws/{cid}")
public class WebSocketServer {
    //存放会话对象
    private static Map<String, Session> sessionMap = new HashMap<>();

    /**
     * 监听连接建立成功
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("cid") String cid){
        System.out.println("客户端:" + cid + "建立连接……");
        sessionMap.put(cid,session);
    }

    /**
     * 监听收到客户端消息
     */
    @OnMessage
    public void onMessage(String msg,@PathParam("cid") String cid){
        System.out.println("这是来自于客户端:" + cid + "的消息:" + msg);
    }

    /**
     * 监听连接关闭
     * @param cid
     */
    @OnClose
    public void  onClose(@PathParam("cid") String cid){
        System.out.println("连接断开:" + cid);
        sessionMap.remove(cid);
    }

    /**
     * 群发消息
     */
    public void sendToAllClient(String msg){
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

编写WebSocket配置类:

/**
 * WebSocket配置类,用于注册WebSocket服务端组件
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

 编写定时任务,用于向客户端发送信息:

@Component
public class MyWebSocketTask {
    @Resource
    private WebSocketServer webSocketServer;

    /**
     * 通过WebSocket每隔5s向客户端发送信息
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void sendMessageToClient(){
        String format = DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now());
        webSocketServer.sendToAllClient("这是来自服务端的消息:" + format);
    }
}

在启动类开启定时任务:

@SpringBootApplication
@EnableScheduling //开启定时任务
public class ExcelProjectApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExcelProjectApplication.class, args);
    }

}

测试结果: