目录
一、项目介绍
如何实现实时同步对局?
二、WebSocket
1、什么是WebSocket?
2、WebSocket的报文格式
opcode
payload len
payload data
3、WebSocket握手过程
4、WebSocket代码的简单编写
三、WebSocket 和 HTTP的关系
1、相同点:
2、不同点
3、联系
一、项目介绍
五子棋双人对战项目一个Web项目,支持多个玩家联网匹配对局,主要有以下三个模块:
1、用户模块
用户的注册和登录。
管理用户的天梯分数、比赛场数、获胜场数。
2、匹配模块
依据用户的天梯积分,实现匹配机制。
3、对战模块
把两个匹配到的玩家放到一个游戏房间中。双方通过网页的形式进行对战。
关键技术:
Java,Spring/Spring Boot/Spring MVC,HTML/CSS/JS/AJAX,MySQL/MyBatis,WebSocket
如何实现实时同步对局?
之前学习的服务器开发,主要使用的是下面这样的模型:
客户端:主动向服务器发起请求,服务器收到之后,返回一个响应。如果客户端不向服务器发送请求,服务器就不会给客户端返回响应。
五子棋项目是要实现实时同步对局的,也就是对方落子后,我这边立马能更新棋盘,我落子后,对方也要能立即更新棋盘。
基于之前学过的HTTP协议,如果我不向服务器发起请求,拿到最新棋盘数据,那么我这里的页面就一直不会改变。
基于上面的问题,想到有以下2种解决方案:
1、客户端每隔一段时间向服务器发起请求,拿到最新的数据。
2、服务器主动给我们返回响应。
第一个方案明显不行,如果间隔时间太短,发送请求的频率会非常高,也就意味着会浪费带宽,浪费资源;间隔时间太长,就可能导致对方已经落子了,但还在间隔时间中,那么我就要继续等客户端发起请求才能拿到最新的数据,明显也不合理。
第二个方案可行,如果对方落子了,服务器接收到请求,主动给我返回响应,这很就合理了。
服务器主动发送响应给客户端,这样的场景称之为:消息推送。
那HTTP协议是否能实现 “消息推送” 场景呢?HTTP自身是难以实现这种消息推送效果的。如果要想实现这样的效果,就需要基于 “轮询” 的机制。而所谓的 “轮询” ,也就是上面的第一种方案,明显是不合理的,会白白浪费很多机器资源(尤其是带宽)。
但有一种协议可以很轻松的实现轮询:WebSocket。
二、WebSocket
1、什么是WebSocket?
1、WebSocket 是HTML5下一种新的协议(WebSocket协议本质上是一个基于TCP的协议)
2、它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽,同时可以达到实时通讯的目的。
3、WebSocket是一个持久化的协议。
2、WebSocket的报文格式
opcode
描述了当前这个WebSocket报文是啥类型。比如:
表示当前这是一个文本帧,还是一个二进制;
表示当前这是一个 ping 帧,还是一个 pong 帧。
payload len
表示当前数据报携带的数据载荷长度。
这个字段本身就是一个变长的,一个WebSocket数据报能承载的载荷长度是非常长的。
payload data
实际报文要传输的数据载荷。
3、WebSocket握手过程
使用网页端,尝试和服务器建立 WebSocket 连接,网页端会先给服务器发起一个 HTTP 请求,这个 HTTP 请求中会带有特殊的 header:
Connection:Upgrade
Upgrade:WebSocket
如果服务器支持 WebSocket,就会返回一个特殊的 HTTP 响应。这个响应的状态码是 101(切换协议)。
然后客户端和服务器之间就可以开始使用 WebSocket 来进行通信了。
4、WebSocket代码的简单编写
后端代码:
@Component
public class TestWebSocket extends TextWebSocketHandler {@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {System.out.println("建立连接");}@Overridepublic void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {System.out.println("收到信息: " + message.getPayload());}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {System.out.println("出现异常");}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {System.out.println("关闭连接");}
}
指定路径:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Autowiredprivate TestWebSocket testWebSocket = new TestWebSocket();@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(testWebSocket, "/test");}
}
前端代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>TestWebSocket</title>
</head>
<body><input type="text" id="message"><button id="submit">提交</button><script>//创建websocket实例var 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发送请求var input = document.querySelector("#message");var button = document.querySelector("#submit");button.onclick = function() {console.log("发送信息: " + input.value);websocket.send(input.value);}
</script>
</body>
</html>
运行程序:
连接成功后,前端、后端都打印建立连接
输入信息,点击提交
关闭浏览器,后端打印
这就是简单的WebSocket通信过程。
三、WebSocket 和 HTTP的关系
1、相同点:
1、都基于 TCP,都是可靠性传输协议。
2、都是应用层协议。
2、不同点
1、WebSocket 是双向通信协议,模拟Socket协议,可以双向发送或接收信息。
2、HTTP 是单向的。
3、WebSocket 是需要浏览器和服务器握手进行建立连接的。
4、HTTP是浏览器向服务器发起请求,从而建立连接,服务器预先并不知道这个连接。
3、联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立连接成功后,真正传输时是不需要HTTP协议的。