WebSocket Day 01:入门案例

前言

欢迎来到WebSocket入门案例系列的第一天!在今天的博客中,我们将一起探索WebSocket的基础知识和使用方法。本系列将以一个简单的入门案例为基础,带领您逐步了解WebSocket的原理和用法。

一、什么是 WebSocket ?

WebSocket是一种在Web应用程序中实现实时双向通信的协议。它提供了一种持久连接,允许服务器主动向客户端推送数据,而不需要客户端发起请求。

传统的Web应用程序使用HTTP协议进行通信,这种通信方式是基于请求-响应模式的。客户端发送请求给服务器,服务器响应请求并返回相应的数据。但是这种方式存在一些限制,特别是对于实时性要求较高的应用场景,如聊天室、股票行情等。

WebSocket通过引入新的协议,提供了一种更高效、更低延迟的通信方式。相对于HTTP,WebSocket具有以下特点:

  1. 双向通信:WebSocket允许客户端和服务器之间进行双向通信,服务器可以主动向客户端推送数据,而不仅仅是响应客户端的请求。这使得实时性要求较高的应用程序能够更加高效地进行数据传输。

  2. 持久连接:WebSocket在建立连接后,保持持久的连接状态,而不需要每次通信都重新建立连接。这消除了每次请求建立连接和断开连接的开销,减少了网络流量和延迟。

  3. 低开销:相对于传统的HTTP请求-响应模式,WebSocket协议的数据帧头部较小,有效减少了通信过程中的数据开销。此外,由于使用持久连接,减少了连接建立和断开的开销。

  4. 兼容性:WebSocket协议基于TCP协议,通过HTTP/HTTPS进行握手协商,并在握手成功后升级为WebSocket连接。由于握手过程使用标准的HTTP/HTTPS协议,因此WebSocket可以通过大多数防火墙和代理服务器。

WebSocket在现代Web应用程序中被广泛应用,特别是对于需要实时通信和即时更新的应用场景。它为开发者提供了一种更加便捷、高效的方式来构建实时性强的Web应用程序。无论是聊天应用、实时博客评论、多人协作工具还是股票行情等都可以借助WebSocket实现更好的用户体验和数据交互。

二、为什么要使用 WebSocket

WebSocket作为一种实现实时双向通信的协议,具有以下优点,这也是为什么要使用WebSocket的原因:

  1. 实时双向通信:传统的Web应用程序都是基于HTTP协议进行请求和响应的,无法实现实时双向通信。而WebSocket协议可以在客户端和服务器之间建立持久连接,实现实时双向通信,从而满足实时性比较强的应用场景。

  2. 低延迟:与HTTP协议相比,WebSocket协议的数据帧头部较小,有效减少了通信过程中的数据开销。由于使用持久连接,减少了连接建立和断开的开销,降低了延迟,提高了应用程序的响应速度和用户体验。

  3. 更好的扩展性:WebSocket协议采用标准的TCP协议,通过HTTP/HTTPS进行握手协商,并在握手成功后升级为WebSocket连接。由于握手过程使用标准的HTTP/HTTPS协议,WebSocket可以通过大多数防火墙和代理服务器。这使得应用程序更容易部署和扩展。

  4. 更低的网络流量:由于WebSocket协议使用二进制帧传输数据,相对于HTTP协议使用文本格式传输数据,WebSocket可以减少网络流量,提高应用程序的效率和性能。

总之,WebSocket协议提供了一种更高效、更低延迟、更实时、更灵活的通信方式,使得实时性较强的应用场景(如聊天室、在线游戏、多人协作工具等)更容易实现。如果您需要构建这些类型的应用程序,那么WebSocket将是您不错的选择。

三、实现一个单的 Hello WebSocket

1、新建项目,结构如下
2、导入依赖
XML 复制代码
<!-- websocket 依赖 -->
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- 打印日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.3.8</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

下面是每个依赖项的作用:

  1. javax.websocket-api:这是一个Java API,用于支持WebSocket通信协议。WebSocket允许在客户端和服务器之间进行双向通信,实时地发送消息和数据。这个依赖项提供了WebSocket的核心接口和类。

  2. logback-classic:这是一个Java日志框架,用于在应用程序中记录和输出日志信息。logback-classic是logback框架的核心组件,它提供了强大的日志记录功能和灵活的配置选项。

  3. lombok:这是一个Java库,通过注解自动化简化了Java代码的编写。使用lombok可以减少样板代码,例如自动生成getter、setter、构造函数等。它提供了一些注解来简化代码的编写和维护,提高开发效率。

3、 编写 controller 类
java 复制代码
@ServerEndpoint("/connect")
@Slf4j
public class WebSocketServer {


    /**
     * 打开连接的方法,当有一个客户端连接服务端的时候
     * 这个方法就会调用一次
     *
     * @OnOpen注解:表示连接
     *
      */
    @OnOpen
    public void onOpen(){
        log.info("客户端已连接" );
    }

    /**
     * 客户端发送消息的方法
     */
    @OnMessage
    public void onMessage(String message,Session session) throws IOException {
        log.info("消息:" + message);
        // 向当前客户端发送一个消息
         session.getBasicRemote().sendText(message);

    }

    /**
     * 当客户端断开连接后调用此方法
     */
    @OnClose
    public void onClose(Session session){
        log.info("客户端已断开连接");
    }

}

在给出每个注解的用途之前,需要说明这段代码是Java中使用WebSocket的示例代码,使用了javax.websocket包提供的注解。

  1. @ServerEndpoint("/connect"):

    • 作用:将Java类标记为WebSocket服务器端点。
    • 解释:这个注解用于标识一个类是WebSocket的服务器端点,指定了客户端连接的URL路径。在上述示例中,客户端需要通过连接至"/connect"路径来与该服务器端点进行通信。
  2. @OnOpen:

    • 作用:定义打开连接时调用的方法。
    • 解释:当有客户端连接到WebSocket服务器端点时,被该注解标记的方法将会被调用。在示例中,onOpen()方法在客户端连接成功后执行,并打印出连接成功的消息。
  3. @OnMessage:

    • 作用:定义接收客户端消息时调用的方法。
    • 解释:当WebSocket服务器端点接收到客户端发送的消息时,被该注解标记的方法将会被调用。在示例中,onMessage()方法接收两个参数:String类型的message表示接收到的消息内容,Session类型的session表示与该客户端的会话。该方法在接收到消息后,会将消息原样发送回客户端。
  4. @OnClose:

    • 作用:定义客户端断开连接时调用的方法。
    • 解释:当与WebSocket服务器端点建立连接的客户端断开连接时,被该注解标记的方法将会被调用。在示例中,onClose()方法接收一个参数:Session类型的session,表示与断开连接的客户端的会话。该方法在客户端断开连接后执行,并打印出断开连接的消息。

这些注解是Java WebSocket API提供的一部分,通过使用这些注解,可以方便地定义WebSocket服务器端点的行为,包括连接建立、消息接收和断开连接等操作。

这个类是一个示例的WebSocket服务器端点类,用于处理客户端与服务器之间的WebSocket通信。主要功能如下:

  1. 打开连接:当有客户端连接到WebSocket服务器端点时,会调用onOpen()方法,并打印出连接成功的消息。

  2. 接收消息:当WebSocket服务器端点接收到客户端发送的消息时,会调用onMessage()方法,并打印出接收到的消息。同时,该方法会将接收到的消息原样发送回客户端。

  3. 断开连接:当与WebSocket服务器端点建立连接的客户端断开连接时,会调用onClose()方法,并打印出断开连接的消息。

这个类是使用了Java WebSocket API提供的注解来定义WebSocket服务器端点的行为。通过这些注解,可以方便地处理WebSocket的连接、消息接收和断开连接等操作。

4、编写一个 html 页面接收数据
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>websocket 客户端</h1>

<script>
    // 构建 websocket 的实例,连接后台 server 的请求地址
    // websocket 在第一次请求时使用 http 协议在连接服务器,告诉服务器
    // 接下来要使用 websocket 进行通信,此时服务器将进行协议升级,会在
    // http 的请求头中带有 upgrade:websocket 的头信息
    var webSocket = new WebSocket("ws://localhost:8080/connect");

    // onopen 方法
    webSocket.onopen = function () {
        // 发送一个消息
        webSocket.send("hello websocket");
    }

    // onmessage 方法,接受服务端发送的信息
    webSocket.onmessage = function (event) {
        alert("服务器的消息:" + event.data);
    }

    // onclose 方法
    webSocket.onclose = function () {
        alert("已断开连接");
    }


</script>

</body>
</html>

这段代码是一个简单的WebSocket客户端示例,用于与WebSocket服务器进行通信。它的作用是:

  1. 创建WebSocket实例:通过var webSocket = new WebSocket("ws://localhost:8080/connect");语句创建了一个WebSocket实例,并指定了连接的服务器地址。

  2. 连接建立:当WebSocket连接成功建立时,会自动触发onopen事件处理函数,其中的webSocket.onopen定义了连接建立时的操作。在示例中,onopen函数中发送了一条消息webSocket.send("hello websocket");到服务器。

  3. 接收消息:当WebSocket客户端接收到来自服务器端的消息时,会触发onmessage事件处理函数,其中的webSocket.onmessage定义了接收消息时的操作。在示例中,当接收到消息时,会通过弹窗的方式显示服务器端发送的消息。

  4. 断开连接:当WebSocket连接关闭时,会触发onclose事件处理函数,其中的webSocket.onclose定义了连接关闭时的操作。在示例中,当连接关闭时,会通过弹窗的方式提示连接已断开。

这段代码展示了一个最基本的WebSocket客户端的工作流程,包括连接建立、消息发送和接收、连接断开等操作。您可以将其用于与WebSocket服务器进行实时通信,实现双向数据传输的功能。根据具体需求,您可以根据这个示例进行定制和扩展,添加更多的业务逻辑和交互功能。

5、运行效果

我们在前端接收到了后台发送来的信息,在后台我们也接受到前端发送的信息,这就是一个简单的多对多的群聊了。

四、实现多人群聊

1、编写 controller
java 复制代码
@ServerEndpoint("/connect")
@Slf4j
public class WebSocketServer {

    /**
     * 用户列表
     */
    private static final List<Session> users = new ArrayList<>();

    /**
     * 打开连接的方法,当有一个客户端连接服务端的时候
     * 这个方法就会调用一次
     *
     * @OnOpen注解:表示连接
     *
     * @param session 表示一个 websocket 客户端的连接会话
     *                每一个客户端连接就会创建一个 session 会话
      */
    @OnOpen
    public void onOpen(Session session){
        log.info("客户端已连接" );
        // 将 session 添加到用户列表中
        users.add(session);
    }

    /**
     * 客户端发送消息的方法
     */
    @OnMessage
    public void onMessage(String message,Session session) throws IOException {
        log.info("消息:" + message);

        // 获取当前时间
        String formattedTime = new SimpleDateFormat("HH:mm:ss").format(new Date());

        // 向当前客户端发送一个消息,包含发送时间
        String messageWithTime = "[" + formattedTime + "] " + message;

        for (Session user : users) {
            // 群发信息
            user.getBasicRemote().sendText(messageWithTime);
        }

    }

    /**
     * 当客户端断开连接后调用此方法
     */
    @OnClose
    public void onClose(Session session){
        log.info("客户端已断开连接");
        // 用户离线
        users.remove(session);
    }

}

解释一下每一行代码的意思:

1)、定义了一个静态的会话列表users,用于存储所有连接到WebSocket服务端的客户端Session对象。
java 复制代码
private static final List<Session> users = new ArrayList<>();
2)、使用@OnOpen注解声明一个方法,该方法用于处理WebSocket客户端连接到服务器后的操作。当有一个新客户端连接到服务器时,该方法会被自动调用。在该方法中,首先记录下客户端连接成功的日志信息,然后将客户端的Session对象保存到静态会话列表中。
javascript 复制代码
@OnOpen
public void onOpen(Session session){
    log.info("客户端已连接" );
    // 将 session 添加到用户列表中
    users.add(session);
}
3)、使用@OnMessage注解声明一个方法,该方法用于处理WebSocket客户端发送消息的操作。当客户端向服务器发送消息时,该方法会被自动调用,并传入消息内容和对应的Session对象。在该方法中,首先记录下客户端发送的消息内容,然后获取当前时间,并将时间和消息内容拼接为一个新的字符串。最后,遍历所有连接到服务器的客户端(即静态会话列表users),并将消息广播给所有客户端。
java 复制代码
@OnMessage
public void onMessage(String message,Session session) throws IOException {
    log.info("消息:" + message);
    // 向当前客户端发送一个消息
//         session.getBasicRemote().sendText(message);

    // 获取当前时间
    String formattedTime = new SimpleDateFormat("HH:mm:ss").format(new Date());

    // 向当前客户端发送一个消息,包含发送时间
    String messageWithTime = "[" + formattedTime + "] " + message;

    for (Session user : users) {
        // 群发信息
        user.getBasicRemote().sendText(messageWithTime);
    }

}
4)使用@OnClose注解声明一个方法,该方法用于处理WebSocket客户端断开连接的操作。当有一个客户端与服务器断开连接时,该方法会被自动调用,并传入断开连接的Session对象。在该方法中,首先记录下客户端断开连接的日志信息,然后将与断开连接的客户端对应的Session对象从静态会话列表中移除。
java 复制代码
@OnClose
public void onClose(Session session){
    log.info("客户端已断开连接");
    // 用户离线
    users.remove(session);
}
2、编写一个页面发送信息
java 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/JQuery文件.txt.js"></script>
</head>
<body>
<h1>聊天室</h1>
<div id="msg"></div>
<input id="message" type="text"/>
<input type="button" value="发送"/>
<script>
    //创建websocket对象
    let ws = new WebSocket("ws://localhost:8080/connect");
    //接收服务端的消息
    ws.onmessage = function(event){
        let message = event.data;
        //将消息放入聊天框
        $('#msg').append(message + '<br>');
    }

    $(function(){
        $(':button').on('click',function(){
            //获取文本消息
            let msg = $('#message').val();
            //发送消息
            ws.send(msg);
            //清空发送框
            $('#message').val('');
        });
    })
</script>

</body>
</html>

这段代码是一个简单的HTML页面,它实现了一个基本的聊天室功能。具体功能如下:

  1. 在页面上显示一个标题为"聊天室"的大标题。
  2. 有一个用于显示聊天消息的<div>元素,它的id属性为"msg"。
  3. 有一个<input>元素,用于输入要发送的消息,它的id属性为"message"。
  4. 有一个<input>按钮,用于发送消息,按钮上显示"发送"。
  5. 使用JavaScript和jQuery库来处理页面上的交互逻辑。

在脚本部分,代码实现了以下功能:

  1. 创建了一个WebSocket对象,通过指定WebSocket服务器的URL来建立与服务器的连接。在这个例子中,服务器的URL是"ws://localhost:8080/connect"。
  2. 设置了一个事件处理程序(ws.onmessage),当接收到来自服务器的消息时,会触发该事件,并将消息显示在聊天框中。
  3. 使用jQuery库,在页面加载完成后,绑定了按钮的点击事件处理程序。当按钮被点击时,获取输入框中的文本消息,并通过WebSocket发送给服务器。然后清空输入框,以便输入下一条消息。

通过将这段代码部署到一个能够处理WebSocket协议的服务器上,你可以创建一个简单的聊天室页面,用户可以在其中实时地发送和接收消息。当用户在输入框中输入消息并点击发送按钮时,消息将通过WebSocket发送给服务器,在服务器上处理后,会将消息广播给所有连接的客户端,以便显示在聊天框中。这样就实现了简单的聊天室功能。

3、运行效果

五、使用局域网 IP 地址实现多人群聊

1、使用命令查看 IP 地址

win + r 打开命令提示符,输入 cmd 回车进入。在控制面板输出 : ipconfig 回车即可查询到自己本机的 IP.

2、在 client.html 页面更改 url

只需要把 localhost 换成自己本机的 IP 地址即可。

3、运行效果

改完 url 地址后,我们在浏览器就不能使用 localhost:8080 去访问了。

使用 IP 地址后的访问路径为:http://本机IP地址:8080/chat.html

4、什么是局域网?

局域网通常用于连接位于同一地理位置的多台计算机和设备。

注意:我们使用的是局域网的 IP 地址去和同学聊天的,如果你们使用的是同一个网络就能够正常的访问这个路径去聊天,如果不在同一网络就不能。比如:教室、学校、家里的WIFI,都可以。

六、总结

本次案例,我们简单的讲解了实现聊天的功能。但是,这只是一个开头,我们要实现真正的聊天还有很多其他的功能要做,比如:登录,登录成功后获取用户的名称。我们这次聊天是不知道用户名的,只有时间和内容,那么在下一章节我将要讲解如何实现登录后实现聊天。

七、gitee 案例

地址:ch01 · qiuqiu/WebSocket-study - 码云 - 开源中国 (gitee.com)

相关推荐
hanbarger22 分钟前
mybatis框架——缓存,分页
java·spring·mybatis
cdut_suye30 分钟前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
EasyDSS33 分钟前
国标GB28181-2022平台EasyGBS:安防监控中P2P的穿透方法
网络协议·php·音视频·p2p
苹果醋342 分钟前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx
小蜗牛慢慢爬行43 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
azhou的代码园1 小时前
基于JAVA+SpringBoot+Vue的制造装备物联及生产管理ERP系统
java·spring boot·制造
网安墨雨1 小时前
常用网络协议
网络·网络协议
wm10431 小时前
java web springboot
java·spring boot·后端
smile-yan1 小时前
Provides transitive vulnerable dependency maven 提示依赖存在漏洞问题的解决方法
java·maven
老马啸西风1 小时前
NLP 中文拼写检测纠正论文-01-介绍了SIGHAN 2015 包括任务描述,数据准备, 绩效指标和评估结果
java