目录
一、项目介绍
五子棋双人对战项目一个Web项目,支持多个玩家联网匹配对局,主要有以下三个模块:
关键技术:
如何实现实时同步对局?
之前学习的服务器开发,主要使用的是下面这样的模型:
五子棋项目是要实现实时同步对局的,也就是对方落子后,我这边立马能更新棋盘,我落子后,对方也要能立即更新棋盘。
基于之前学过的HTTP协议,如果我不向服务器发起请求,拿到最新棋盘数据,那么我这里的页面就一直不会改变。
基于上面的问题,想到有以下2种解决方案:
第一个方案明显不行,如果间隔时间太短,发送请求的频率会非常高,也就意味着会浪费带宽,浪费资源;间隔时间太长,就可能导致对方已经落子了,但还在间隔时间中,那么我就要继续等客户端发起请求才能拿到最新的数据,明显也不合理。
第二个方案可行,如果对方落子了,服务器接收到请求,主动给我返回响应,这很就合理了。
服务器主动发送响应给客户端,这样的场景称之为:消息推送。
那HTTP协议是否能实现 “消息推送” 场景呢?HTTP自身是难以实现这种消息推送效果的。如果要想实现这样的效果,就需要基于 “轮询” 的机制。而所谓的 “轮询” ,也就是上面的第一种方案,明显是不合理的,会白白浪费很多机器资源(尤其是带宽)。
但有一种协议可以很轻松的实现轮询:WebSocket。
二、WebSocket
1、什么是WebSocket?
2、WebSocket的报文格式
opcode
payload len
payload data
3、WebSocket握手过程
使用网页端,尝试和服务器建立 WebSocket 连接,网页端会先给服务器发起一个 HTTP 请求,这个 HTTP 请求中会带有特殊的 header:
Connection:Upgrade
Upgrade:WebSocket
如果服务器支持 WebSocket,就会返回一个特殊的 HTTP 响应。这个响应的状态码是 101(切换协议)。
然后客户端和服务器之间就可以开始使用 WebSocket 来进行通信了。
4、WebSocket代码的简单编写
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
后端代码:
@Component
public class TestWebSocket extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("建立连接");
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
System.out.println("收到信息: " + message.getPayload());
}
@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("关闭连接");
}
}
指定路径:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private TestWebSocket testWebSocket = new TestWebSocket();
@Override
public 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通信过程。