websocket聊天(全源码)

区别:我认为的websocket和轮询的区别

轮询是客户端定期向服务端发送请求,目的是获取的信息

websocket则是服务端直接向客户端发送想要获取的信息

配置jdk17 idea 2022

代码

pom

<?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>3.2.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>wsocket</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>wsocket</name>
    <description>wsocket</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.32</version>
        </dependency>
        <!-- websocket消息推送 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.springframework</groupId>-->
<!--            <artifactId>spring-websocket</artifactId>-->
<!--            <version>6.0.9</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.tomcat.embed</groupId>-->
<!--            <artifactId>tomcat-embed-websocket</artifactId>-->
<!--            <version>10.1.20</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.tomcat.embed</groupId>-->
<!--            <artifactId>tomcat-embed-websocket</artifactId>-->
<!--            <version>9.0.78</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-websocket</artifactId>
            <version>10.1.20</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 配置类

package com.example.wsocket.spring;

import com.example.wsocket.java.WebSocketConfig;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 */
@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {
    @Resource
    MyWsHandler myWsHandler;
    @Resource
    MyWsInterceptor myWsInterceptor;
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWsHandler,"/myWs1")
                .addInterceptors(myWsInterceptor)
                .setAllowedOrigins("*");
    }
    //访问的位置,设置拦截器,设置拦截范围
}

websocket周期设置

package com.example.wsocket.spring;

import cn.hutool.core.text.StrBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
    物理程序
 */
@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {
    private static Map<String,SessionBean> sessionBeanMap;
    private static AtomicInteger clientIdMaker;
    private static StringBuffer stringBuffer;
    //初始化
    static {
        sessionBeanMap = new ConcurrentHashMap<>();
        clientIdMaker = new AtomicInteger(0);
        stringBuffer = new StringBuffer();
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());
        sessionBeanMap.put(session.getId(),sessionBean);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立连接");
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"进入了群聊<br/>");
        sendMessage(sessionBeanMap);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");
        sendMessage(sessionBeanMap);
    }
    //异常时
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if (session.isOpen()){
            session.close();
        }
        sessionBeanMap.remove(session.getId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        int clientId = sessionBeanMap.get(session.getId()).getClientId();
        sessionBeanMap.remove(session);
        log.info(clientId+"关闭了连接");
        stringBuffer.append(clientId+"退出了群聊<br/>");
        sendMessage(sessionBeanMap);
    }

    public void sendMessage(Map<String,SessionBean> sessionBeanMap){
        for(String key:sessionBeanMap.keySet()){{
            try {
                sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));
            } catch (IOException e) {
                log.info("出错啦");
            }
        }}
    }

//    //定时任务
//    @Scheduled(fixedDelay = 2000)//多少秒执行1次
//    public void sendMessage() throws IOException {
//        for (String key:sessionBeanMap.keySet()){
//            sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(":心跳"));
//        }
//    }
}

拦截器

package com.example.wsocket.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.Map;

/**
 * @authorGH
 * @company www.1248163489.com
 */
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

sessionBean


import jakarta.websocket.Session;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.server.WebSession;
import org.springframework.web.socket.WebSocketSession;

/**
 * @authorGH
 * @company www.1248163489.com
 */
@Data
@AllArgsConstructor

public class SessionBean {
    /**
     *
     *@param
     */
    private WebSocketSession webSocketSession;
    private Integer clientId;
}

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p style="border: 1px solid black;width: 400px;height: 600px" id="talkMsg"></p>
<input id="message" />
<button id="sendBtn" onclick="sendMsg()">发送</button>
</body>
<script>
    let ws = new WebSocket("ws://localhost:8080/myWs1")
    ws.onopen=function (){
    }
    ws.onmessage=function (message) {
        document.getElementById("talkMsg").innerHTML = message.data
    }
    function sendMsg() {
        ws.send(document.getElementById("message").value)
        document.getElementById("message").value=""
    }
</script>
</html>

  • 19
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WebSocket是一种在Web应用程序中实现实时双向通信的技术。它通过一种持久化的连接机制,允许服务器主动将数据推送给客户端,而不需要客户端发起请求。下面是WebSocket的源码解析。 WebSocket源码主要分为服务器端和客户端两部分。 在服务器端,WebSocket源码主要包含以下几个核心类: 1. ServerSocket:用于监听并接受客户端的连接请求。它通过创建ServerSocket实例并指定端口来启动WebSocket服务器。 2. Socket:用于与客户端进行通信。当ServerSocket接受到客户端的连接请求后,会创建一个Socket实例来处理与该客户端的通信。 3. WebSocketHandler:负责解析和处理客户端发送的WebSocket请求,以及发送响应给客户端。它会使用WebSocket协议将数据进行封装和解封装。 4. WebSocketFrame:用于表示WebSocket消息帧。它包含了消息类型、消息长度以及消息内容等信息。 在客户端,WebSocket源码主要包含以下几个核心类: 1. WebSocket:用于与服务器端进行通信。它通过创建WebSocket实例来连接服务器,并发送和接收消息。 2. WsClient:负责处理WebSocket连接的建立和断开,以及发送和接收消息的操作。 3. Connection:表示与服务器端的连接。它通过创建Socket实例来建立与服务器的连接,并负责处理与服务器的通信。 在WebSocket源码中,需要注意以下几个要点: 1. WebSocket协议:WebSocket协议是基于HTTP协议的,通过在握手阶段进行协议升级,实现从HTTP到WebSocket的切换。在源码中需要解析和处理WebSocket协议。 2. 数据压缩:WebSocket支持将数据进行压缩,以减少传输的数据量。源码中需要实现数据压缩和解压缩的功能。 3. 安全性:WebSocket可以通过SSL/TLS协议进行加密以保证数据的安全性。在源码中需要支持SSL/TLS的加密和解密操作。 总结:WebSocket源码实现了服务器端和客户端之间的实时双向通信。通过WebSocket协议和各种实用功能的支持,实现了高效的数据传输和安全的通信。 ### 回答2: WebSocket 是一种基于 TCP 协议的全双工通信协议,它可以在客户端和服务器之间建立持久连接,实现实时的双向通信。 WebSocket 协议相较于传统的 HTTP 协议具备以下几个显著特点: 1. 双向通信:WebSocket 具备客户端和服务器之间的全双工通信能力,两者可以同时发送和接收数据。 2. 实时性:WebSocket 的连接一旦建立起来,可以保持长时间的持久连接,避免了 HTTP 协议每次请求都需要重新建立连接的开销。这样就可以实现实时性要求较高的应用场景,比如聊天室、股票行情等。 3. 更少的数据传输:相较于 HTTP 协议,WebSocket 的数据帧头信息更小,且在数据传输时采用二进制格式,能够更高效地传输数据。 4. 跨域通信:WebSocket 协议支持跨域通信,客户端可以发起到不同域的服务器的连接请求,打破了浏览器同源策略的限制。 WebSocket 的源码实现可以参考不同编程语言的库或框架提供的实现。比如在 JavaScript 中,可以通过使用浏览器原生提供的 WebSocket API 来实现。 WebSocket 源码的实现主要包括以下几个关键步骤: 1. 建立连接:客户端通过 WebSocket 对象的构造函数创建一个 WebSocket 实例,并指定需要连接的服务器地址。客户端与服务器建立连接后,会进行握手协议,完成连接的建立。 2. 数据传输:连接建立成功后,客户端和服务器可以进行双向的数据传输。客户端可以通过发送消息的方法将数据发送给服务器,而服务器通过监听消息事件来接收客户端发送的数据。服务器也可以向客户端发送消息,客户端通过监听消息事件来接收服务器发送的数据。 3. 处理错误:在 WebSocket 连接过程中,如果发生错误,客户端和服务器都会触发错误事件以及对应的错误处理函数,从而进行错误处理。 4. 断开连接:当连接不再需要时,客户端或服务器可以主动关闭连接,释放相关资源。同时,也可以通过监听关闭事件来处理连接关闭的情况。 通过阅读 WebSocket 源码的实现,可以更深入地了解其中的细节及其底层的实现原理,从而更好地应用和优化 WebSocket 的相关开发。 ### 回答3: WebSocket是一种实时通信协议,用于在客户端和服务器之间建立双向通信的连接。它使用HTTP作为握手协议,并在握手成功后将连接升级为全双工通信通道。 WebSocket的源码包括服务器端和客户端的实现。以下是一些常见的WebSocket源码实现细节: 1. 服务器端代码:服务器端的WebSocket源码主要包括HTTP握手和WebSocket连接的建立。服务器接收到客户端的WebSocket升级请求后,会进行一系列握手流程,并在握手成功后将连接升级为WebSocket连接。服务器端的源码通常会包括处理握手请求、解析数据帧、处理连接维护和消息处理等功能。 2. 客户端代码:客户端的WebSocket源码主要包括与服务器进行握手和维护WebSocket连接的工作。客户端建立WebSocket连接时,会向服务器发送HTTP握手请求并解析服务器的握手响应。握手成功后,客户端可以通过WebSocket连接与服务器进行实时通信。客户端的源码通常会包括握手请求发送、握手响应解析、数据帧封装与解析等功能。 3. 数据帧封装与解析:WebSocket数据帧是协议中的最基本通信单位。服务器和客户端在发送和接收数据时,会将数据封装成数据帧格式进行传输。数据帧的格式包括一些固定的头部信息和可变长度的负载数据。源码中的数据帧封装和解析部分负责将待发送的数据封装成数据帧格式,以及在接收到数据帧后将其解析成可读的数据。 总结起来,WebSocket源码实现了协议的基本功能,包括协议握手、连接建立、数据帧封装与解析等。通过阅读WebSocket源码,可以更好地理解和学习WebSocket协议的实现原理和工作机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值