基于WebSocket模拟直播间评论的实现

平台奖励创作,可能会升级VIP文章,可以移步我的公众号:【编程朝花夕拾】,且可获取首发内容。

01 引言

之前探索了一下直播间实时评论的的背后技术,这一节,我们将选用最经典的WebSocket的模拟这一功能的实现。

WebSocket可以基于Netty实现,也可以基于Springboot实现。本节使用Springboot自带的WebSocket实现。

02 Maven依赖的引入

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

<!-- 编写页面使用 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 序列化对象工具类 -->
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
</dependency>

03 直播间实时评论模拟实战

下来我们将一步步搭建WebSocket,实现模拟直播间。具体的使用可以参见官方的文档说明:

https://docs.spring.io/spring-framework/docs/5.3.31/reference/html/web.html#websocket-server

3.1 创建WebSocket处理器

官方案例给的比较简单,我们来实现属于我们自己的处理器。

  • ① 建立连接,保存当前的客户端
  • ② 处理文本消息
  • ③ 连接关闭后,删除当前客户端
  • ④ 模拟敏感词处理-

建立连接

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    log.info("链接建立成功......");
    String sessionId = session.getId();
    WebSocketSession webSocketSession = SESSION_MAP.get(sessionId);
    if (webSocketSession == null) {
        SESSION_MAP.put(sessionId, session);
    }

    // 发送消息
    noticeClient(session, sessionId.substring(0, 5) + "*** 进入了直播间");
}

接收消息

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    // 收到客户端发送的消息
    String sessionId = session.getId();
    // 敏感词操作
    String msg = doSensitivewords(message);
    log.info("sessionId={} 收到消息={}", sessionId, msg);

    noticeClient(session, msg);
}

关闭连接

@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    log.info("链接关闭......");
    String sessionId = session.getId();
    SESSION_MAP.remove(sessionId);

    noticeClient(session, sessionId.substring(0, 5) + "*** 离开了直播间");
}

模拟敏感词处理

private String doSensitivewords(TextMessage message) {
    String payload = message.getPayload();
    // 假设敏感词为【死亡】
    if (payload.contains("死亡")) {
        payload = payload.replace("死亡", "***");
    }
    return payload;
}

通知客户端

这里通知客户端,是需要通知所有的已连接的客户端。

private void noticeClient(WebSocketSession session, String message) {
        String sessionId = session.getId();

        // 发送消息,在线人数加1
        Map<String, Object> msgMap = new HashMap<>();
        msgMap.put("msg", message);
        msgMap.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        msgMap.put("sessionId", sessionId.substring(0, 5)+ "***");
        msgMap.put("count", SESSION_MAP.values().size());

        SESSION_MAP.values().forEach(item -> {
            try {
                item.sendMessage(new TextMessage(JSON.toJSONString(msgMap)));
                log.info("发送消息完成");
            } catch (IOException e) {
                log.error("发送消息异常......", e);
            }
        });
    }

3.2 配置WebSocket

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer{

    @Autowired
    MyWebSocketHandler myWebSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWebSocketHandler, "/ws/live").setAllowedOrigins("*");
    }
}

/ws/liveWebSocket 的连接。另外还需要设置允许的请求源,这里允许所有,否则无法连接服务器。

myWebSocketHandler 是上一节创建的处理器。

3.3 客户端的处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模拟直播室实时评论的功能</title>
</head>
<body>
    <div style="width: 700px; margin: 0 auto;">
        <div>
            <h1>直播间</h1>
            <div>
                <span>直播间人数:</span>
                <span style="color: blue" id="count">1</span>
            </div>
            <div id="message" style="height: 300px; overflow: auto; border: 1px solid #ccc;"></div>
        </div>
        <div style="margin-top: 10px;">
            <input type="text" id="messageInput">
            <button onclick="sendMessage()">发送评论</button>
        </div>
    </div>
</body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
    let socket = new WebSocket("ws://localhost:8080/ws/live");

    // 打来链接
    socket.onopen = function(event) {
        console.log("WebSocket is open now.");
    };

    // 处理消息
    socket.onmessage = function(event) {
        let message = event.data;
        console.log(event);
        console.log("Received message: " + message);
        let json = JSON.parse(message);
        $("#message").append('<p><span style="color: blueviolet">'+json.time+ '('+json.sessionId+'):</span>'+ json.msg + '</p>');
        $("#count").text(json.count);
    };

    // 关闭链接
    socket.onclose = function(event) {
        console.log("WebSocket is closed now.");
    };

    // 发送消息
    function sendMessage() {
        let message = $("#messageInput").val();
        socket.send(message);
        $("#messageInput").val("");
    }
</script>
</html>

客户端主要功能,就是建立连接,接收消息和发送消息。

3.4 测试

第一个人进入直播间

第二个人进入直播间

发送消息

任何一个人发送消息后,都会显示在直播间里面。

敏感词处理

用户输入了【死亡笔记】,检测到【死亡】,直接处理成【***】

关闭客户端

04 小结

上面简单的模拟实现了直播间实时评论的功能。业务功能的大致实现思路就是如此。但是在实际应用中需要考虑很多因素,比如安全、性能、资源等。

安全性,需要在进入直播间校验当前用户的身份或者其他限制。

性能,直播间能够抗住多少并发,限制在线人数等。

资源,用户正常关闭客户端本身没有问题,如果因为网络问题,用户无法关闭客户端,或者服务端没有及时删除掉已经离线的客户端,就会造成服务端资源的浪费

如何检测客户端是否已经掉线,敏感词的动态处理、用户禁言、提出直播间等这些隐藏功能可能都需要实现的。

万丈高楼平地起,任何复杂的业务都是由简单的逻辑一点点的积累而成的。希望这次简单的分享,能够带给你灵感。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智_永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值