网页版五子棋—— WebSocket 协议

devtools/2024/11/6 11:24:30/

目录

·前言

一、背景介绍

二、原理解析

1.连接过程(握手)

2.报文格式

三、代码示例

1.服务端代码

(1)TestAPI 类

(2)WebSocketConfig 类

2.客户端代码

3.代码演示 

·结尾


·前言

        从本篇文章开始,我就来与大家分享网页版五子棋项目的一个实现过程了,这个项目一共有以下几个核心模块:用户模块、匹配模块、对战模块,后面文章会按照顺序来对每个模块进行介绍,并且此项目用到的核心技术有:Spring/SpringBoot/SpringMVC、WebSocket、MySQL、MyBatis、HTML/CSS/JS/AJAX,本篇文章来介绍一下 WebSocket 协议的内容、原理及代码示例,下面就开始本篇文章的内容介绍。

一、背景介绍

        WebSocket 是一种支持网页端与服务端保持长连接的消息推送机制,什么是消息推送机制呢?在我们传统的 web 程序中,都是属于“一问一答”的形式,如下图所示:

         这种情况下,服务器是被动的一方,如果客户端不主动发送请求,服务器就不会主动给客户端响应,我们所要编写的五子棋程序使用这种形式就会出现下面的情况:

        此时由于玩家2 没有向服务器发送请求,就会导致玩家2 收不到玩家1 的落子情况,消息推送机制就是可以让服务器主动给客户端发送数据,如果想使用传统“一问一答”的形式实现消息推送的效果也是可以做到,那就要采用“轮询”的方式,如下图所示:

         此时,在玩家1 没有落子之前,玩家2 就会以一定的时间间隔不断的向服务器发起请求,来询问玩家1 有没有落子,很明显,使用这种轮询操作的体验效果与开销与询问的时间间隔有关,关系如下:

  • 如果轮询时间间隔比较长:玩家1 落子之后,玩家2 不能及时获取到落子结果,对弈的体验性降低;
  • 如果轮询时间间隔比较短:虽然及时性得到改善,但是玩家2 就要浪费更多的机器资源,比如:网络带宽。

         为了更好的实现消息推送机制,在我们五子棋项目中,就引入了 WebSocket 协议,这是一种接近于 TCP 级别的通信方式,一旦建立好连接,客户端与服务器都可以主动向对方发送数据。

        基于 WebSocket 来实现的消息推送在五子棋项目中就会起到下图的效果:

         此时,玩家1 的落子请求发送给服务器后,服务器就会自动把响应推送给玩家1 与玩家2 。

二、原理解析

1.连接过程(握手)

        在我们使用网页端想尝试和服务器建立 WebSocket 连接会经过以下几个步骤:

  1. 网页端先给服务器发送一个 HTTP 请求,请求中会带有特殊的 header(Connection:Upgrade、Upgrade:WebSocket)这个 header 就是告诉服务器,我们需要进行协议的升级;
  2. 如果服务器支持 WebSocket,就会返回一个特殊的 HTTP 响应,这个响应的状态码是 101 (切换协议);
  3. 客户端与服务器之间开始使用 WebSocket 来进行通信。

        上述的具体过程可以如下图所示:

2.报文格式

        WebSocket 的报文格式如下图所示:

        WebSocket 也是一种应用层的协议,它的下层是基于 TCP 的,下面我来对上图的部分内容做一个简单介绍:

  •  FIN:当这里的内容为 1 时,表示要断开 WebSocket 连接;
  • RSV1~3:这是保留位,一般为0;
  • opcode:这是操作码,描述了当前 WebSocket 报文是什么类型,它可以描述当前报文是一个文本帧还是一个二进制帧,是一个 ping 帧还是一个 pong 帧;
  • Payload length:这是表示当前数据报携带的数据载荷的长度,它是一个可边长的字段,一个 WebSocket 的数据报能承载的载荷长度是非常长的;
  • Payload data:这是表示当前 WebSocket 实际报文要传输的数据载荷。

三、代码示例

        下面我来实现一个简单的 WebSocket 代码,这里服务端的代码由 Java 来编写,客户端的代码由 JS 来编写。

1.服务端代码

        编写服务端代码的流程如下:

  1. 创建出一个 Spring 项目,在 Spring 中内置了 WebSocket 可以直接使用;
  2. 创建 api.TestAPI 类,这个类用来处理 WebSocket 请求,并返回响应;
  3. 创建 config.WebSocketConfig 类,这个类用来配置请求路径和 TextWebSocketHandler 之间的对应关系。

         代码结构如下所示:

(1)TestAPI 类

         在这里,继承了 TextWebSocketHandler 这个类,我们需要重写里面的几个方法,如下图所示的选中方法:         关于重写的这四个方法都是什么作用,我在代码的注释中会进行详细的标注,那么关于 TestAPI 这个类的全部代码及注释如下所示:

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.TextWebSocketHandler;// 添加 @Component 注解,交给 Spring 管理
@Component
public class TestAPI extends TextWebSocketHandler {@Override// 连接就绪后就会触发这个方法来告知连接成功public void afterConnectionEstablished(WebSocketSession session) throws Exception {System.out.println("连接成功");}@Override// 客户端/服务器 给 服务器/客户端 发送信息通过这个方法就可以接收到信息protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {System.out.println("收到消息" + message.getPayload());// 让服务器收到消息之后原封不动的返回session.sendMessage(message);}@Override// 传输出现异常就会触发这个方法public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {System.out.println("连接异常");}@Override// 如果客户端/服务器关闭连接就会执行这个方法public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {System.out.println("连接关闭");}
}

(2)WebSocketConfig 类

         在这里,实现了 WebSocketConfigurer 接口,用于 WebSocket 的相关配置,代码及介绍注释如下所示:

import com.example.springgobang.aip.TestAPI;
import org.springframework.beans.factory.annotation.Autowired;
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;// @EnableWebSocket 注解用来告诉 Spring 这是配置 WebSocket 的类
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {// 自动注入@Autowiredprivate TestAPI testAPI;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 当客户端连接 /test 这样的路径后就会触发 testAPI 进而调用其内部的方法registry.addHandler(testAPI,"/test");}
}

2.客户端代码

        这里我们编写一个 html 页面来与服务器代码建立 WebSocket 连接,TestAPI.html 页面代码及介绍如下所示:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!--输入框--><input type="text" id="message"><!--按钮--><button id="sendButton">发送</button><script>// 创建 WebSocket 实例, 要保证这里的路径与配置的路径一致 /testlet webSocket = new WebSocket("ws://127.0.0.1:8080/test");// 连接成功后会调用这个函数webSocket.onopen = function() {console.log("连接成功");}// 收到信息后会调用这个函数webSocket.onmessage = function(e) {console.log("收到消息: " + e.data);}// 连接异常时会执行这个函数webSocket.onerror = function() {console.log("连接异常");}// 连接断开后会调用这个函数webSocket.onclose = function() {console.log("连接关闭");}// 实现点击按钮后,通过 WebSocket 发送请求let messageInput = document.querySelector('#message');let sendButton = document.querySelector('#sendButton');sendButton.onclick = function() {console.log("发送消息: " + messageInput.value);// send 函数就会把输入框中的内容发送出去webSocket.send(messageInput.value);}</script>
</body>
</html>

3.代码演示 

        此时,关于 WebSocket 的演示代码就编写完毕了,下面我们来启动程序,在电脑的浏览器上输入:http://127.0.0.1:8080/TestAPI.html 来访问 TestAPI.html 页面,然后鼠标右键点击检查,或者按键盘上的 F12 按钮,进入控制台观察日志信息,然后在输入框中输入数据点击发送就可以观察到效果,具体的效果演示如下图所示:

        此时在服务端断开连接(停止程序),结果如下图所示:

        通过上述的运行结果可以看出来,服务端可以随时调用 session.sendMessage() 方法来给客户端发送响应,从而可以实现消息推送这样的机制。

·结尾

        文章到此就要结束了,本篇文章介绍了 WebSocket 协议的一些基础原理,并用 WebSocket 进行了简单的网络编程,来演示了消息推送的效果,这是五子棋项目重要逻辑的实现依据,使用 WebSocket 就可以保证对弈双方可以实时在页面上观察到对方的落子情况,介绍完 WebSocket 之后就要开始五子棋项目的正式编写了,如果对本篇文章的内容有所疑惑,欢迎在评论区进行留言,我们下一篇文章再见吧~~~


http://www.ppmy.cn/devtools/131742.html

相关文章

Mac删除软件,步骤超简单!

Mac删除软件&#xff0c;有人容易&#xff0c;有人难&#xff0c;但不管怎么样&#xff0c;你确定你删除的软件是彻底干净的吗&#xff1f;看看张女士的故事咯。 周末的下午&#xff0c;张女士坐在咖啡馆里&#xff0c;端着一杯热气腾腾的拿铁&#xff0c;准备用她的MacBook处…

HTB:PermX[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are listening on PermX? 使用nmap对靶机TCP端口进行开放扫描 2.What is the default domain name used by the web server on the box? 使用curl访问靶机80端口 3.On what subdomain of permx.htb is there an o…

【spark的集群模式搭建】Standalone集群模式的搭建(简单明了的安装教程)

文章目录 1、使用Anaconda部署Python2、上传、解压、重命名3、创建软连接4、配置spark环境变量5、修改 spark-env.sh配置文件6、启动hdfs&#xff0c;创建文件夹7、修改spark-defaults.conf配置文件8、修改workers配置文件9、修改log4j.properties配置文件&#xff08;可选&…

掌握 Jest 配置文件:优化单元测试的灵活性与可维护性

引言 在现代软件开发中&#xff0c;单元测试是确保代码质量和稳定性的关键步骤。Jest 是一个广泛使用的 JavaScript 测试框架&#xff0c;提供了丰富的配置选项来优化测试过程。通过配置文件&#xff0c;开发者可以更灵活地控制测试环境&#xff0c;确保测试的可靠性和可维护性…

系统学英语 — 句子成分

句子成分 句子成分的类型包括&#xff1a;主、谓、宾、表、定、状、补、同位语。 成分作用充当词类举例主语句子的主体&#xff0c;动作的发出者。表示什么人、什么事。1&#xff09;名词性词&#xff08;名词、代词、数词、非谓语动词&#xff09;&#xff1b;2&#xff09;…

C#语言发展历史

1.C# 1.0 发布于2002年1月 和 Visual Studio .NET 2002 一起发布的 C# 版本 1.0 非常像 Java。其目标是成为一种“简单、现代、通用的面向对象的语言”。当时&#xff0c;看起来像 Java 意味着它实现了早期的设计目标。 不过如果现在回顾 C# 1.0&#xff0c;你会觉得有点晕。 它…

QCustomPlot添加自定义的图例,实现隐藏、删除功能(一)

文章目录 实现步骤:实现代码:代码讲解:功能说明:优化建议:其他参考:要实现一个支持勾选并可以控制曲线显示和隐藏的自定义 QCPLegend 类,可以通过继承 QCPLegend 并重写其相关方法来实现。我们需要添加一个自定义的复选框元素,并捕捉用户交互来实现曲线的隐藏和显示。…

VSCode 与 HBuilderX 介绍

Visual Studio Code (VSCode) Visual Studio Code (VSCode) 是一款由 Microsoft 开发的源代码编辑器&#xff0c;支持多种编程语言&#xff0c;并且是免费和开源的。它在开发者社区中非常受欢迎&#xff0c;因其强大的功能和高度的可定制性而受到赞誉。 特点 轻量级且强大&am…