网页版五子棋—— WebSocket 协议

news/2024/11/14 2:08:36/

目录

·前言

一、背景介绍

二、原理解析

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/news/1546808.html

相关文章

模型减肥秘籍:模型压缩技术 CNN基础

这里是Datawhale的组队学习活动&#xff0c;主要介绍的是模型压缩技术。后续将以CNN网络为基础点&#xff0c;带领大家领略模型压缩的魅力。首先是回顾一下一些关于CNN的基础知识。 参考链接&#xff1a; 模型减肥秘籍&#xff1a;模型压缩技术-课程详情 | Datawhale datawh…

Linux驱动开发基础——Hello驱动程序(一)

目录 一、Hello驱动 一、Hello驱动 我们选用的内核都是 4.x 版本&#xff0c;操作都是类似的&#xff1a; 1.1、APP 打开的文件在内核中如何表示 open函数原型&#xff1a; int open(const char *pathname, int flags, mode_t mode); 仔细看函数的参数&#xff0c;再对比看 内…

【大数据学习 | HBASE】hbase shell基础实操

1. 查看hbase状态 # 进入hbase 命令行 hbase shell status 我这里没启用高可用hbase 1 active master, 0 backup masters, 2 servers, 1 dead, 1.0000 average load Took 5.2635 seconds 2. 查看版本号 version hbase:002:0> version 2.4.11, r7e672a0da0586e6b7449…

从0开始学习Linux——文件管理

往期目录&#xff1a; 从0开始学习Linux——简介&安装 从0开始学习Linux——搭建属于自己的Linux虚拟机 从0开始学习Linux——文本编辑器 从0开始学习Linux——Yum工具 从0开始学习Linux——远程连接工具 从0开始学习Linux——文件目录 从0开始学习Linux——网络配置 从0开…

机器学习——简单线性回归、逻辑回归

简单线性回归 线性回归用于预测一个连续的数值输出&#xff08;因变量&#xff09;&#xff0c;其模型假设输入特征&#xff08;自变量&#xff09;和输出之间存在线性关系。基本的线性回归模型如下&#xff1a; 损失函数 线性回归通常通过最小二乘法来估计回归系数。最小二乘法…

Anaconda 和 Miniconda

Anaconda 和 Miniconda&#xff1a;讲解与使用指南 目录 什么是 Anaconda 和 Miniconda&#xff1f;Anaconda 和 Miniconda 的区别Anaconda 和 Miniconda 的安装步骤 安装 Anaconda安装 Miniconda 基本使用指南 创建和管理虚拟环境安装和管理包更新和管理 Conda 数据科学工具…

2024.6月GESP一级真题讲解(含视频讲解)

1、2024.6月GESP一级真题代码 //休息时间 #include<bits/stdc.h> using namespace std; int main(){int h,m,s,k;//59cin>>h>>m>>s>>k;//1h60m 1m60s 1h3600 k3600 123/100int mhk/3600h;int mmk/60%60m;int msk%60s;if(ms>60){ms-60;mm1…

服务器硬件介绍

计算机介绍 现在的人们几乎无时无刻都在使用电脑&#xff01;而且已经离不开电脑了。像桌上的台式电脑(桌机)、笔记本电脑(笔电)、平板电脑、智能手机等等&#xff0c;这些东西都算是电脑。 台式机电脑介绍 计算机又被称为电脑。台式机电脑主要分为主机和显示器两个部分&…