当前位置:   article > 正文

项目-双人五子棋对战: websocket的讲解与使用 (1)_websocket五子棋

websocket五子棋

完整代码见: 邹锦辉个人所有代码: 测试仓库 - Gitee.com

项目介绍

接下来, 我们将制作一个关于双人五子棋的项目, 话不多说先来理清一下需求.

1.用户模块

用户的注册和登录

管理用户的天梯分数, 比赛场数, 获胜场数等信息.

2.匹配模块

依据用户的天梯积分, 实现匹配机制.

3.对战模块

把两个匹配到的玩家放到同一个游戏房间中, 双方通过网页的形式来进行对战比赛.

可见这个项目是围绕这三层为中心来写的, 以后的项目开发也是围绕着这三个方面展开.

核心问题

之前在学网络的时候, 我们也学到客户端-服务器这一个经典结构, 即客户端向服务器发送请求, 服务器构造响应, 服务器将响应返回给客户端.(应用的对应也是HTTP协议)

但是在这个项目的对战模块中, 有一个核心的问题: 我们都知道, 当在进行五子棋对战时, 一方落子, 不仅需要在自己的客户端中显示, 也要在对手的客户端中显示.  但是关键是, 对手的客户端没有发起请求, 那么服务器怎么响应?

因此, 我们是需要服务器主动给客户端响应的模式的, 也叫消息推送.

当前我们学习过的HTTP其实也能完成这样的功能, 主要是通过轮询的方式, 即每过一定时间客户端就主动给服务器发送一个请求, 以获取响应. 但这样也有一些问题:

1. 轮询时间设置的比较短, 相应消耗的带宽资源就比较多(浏览器需要源源不断地向服务器发送http请求, 而http请求可能会带有较长的头部, 真正传输的数据可能只是很小一部分, 这样就会浪费很多带宽资源).

2. 轮询时间设置的比较长, 就会导致延迟较高, 影响用户体验.

那么有没有一种合适的方式来解决这个问题呢? 当然有, WebSocket. 

WebSocket

WebSocket工作原理

WebSocket是一个持久化的协议, 使得客户端与服务器之间的数据交换变得更简单, 它允许服务器主动向客户端推送数据, 在WebSocketAPI中, 浏览器和服务器只需要一次握手, 两者就可以创建持久性的连接, 并进行双向数据传输.

WebSocket其实和http协议没有什么关系, 只是为了兼容浏览器的握手规范, 也是说他是http协议上的一种补充;

在WebSocket的握手过程中, 首先使用网页端, 尝试和服务器建立WebSocket连接. 网页端会先给服务器发起一个HTTP请求, 这个HTTP请求中会带有特殊的header: Upgrade和Connection. (即Connection: Upgrade, Upgrade: WebSocket), 这两个header其实就是在告知服务器, 我们要进行协议升级,  如果服务器支持WebSocket, 就会返回一个特殊的HTTP响应, 这个响应的状态码是101.(切换协议), 客户端和服务器之间就使用WebSocket开始通信.

这样就只需要一次HTTP请求, 就可以源源不断地传送消息, 这也叫消息推送场景

WebSocket在项目中的使用?

前后端介绍

WebSocket在前端JS和后端都发挥了重要作用, 实现了实时, 双向的通信. 前端JS通过WebSocket API和后端服务器建立连接, 发送和接收数据以及处理各种事件; 后端服务器负责监听连接, 处理数据, 推送数据以及管理连接资源

WebSocket的生命周期

onOpen: 连接建立时触发;

onMessage: 客户端接收到服务器数据时触发;

onError: 发生错误时触发;

onClose: 连接关闭时触发. 

在后端中主要是重写以下四个方法以实现上述:

  1. //websocket生命周期的演示
  2. @Component
  3. public class TestAPI extends TextWebSocketHandler {
  4. /**
  5. * 当一个新的websocket连接建立时, 这个方法被调用
  6. * webSocketSession对象表示一个WebSocket会话, 用于发送和接收消息
  7. * 该方法在连接成功后打印一条消息
  8. * @param session
  9. * @throws Exception
  10. */
  11. @Override
  12. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
  13. System.out.println("连接成功");
  14. }
  15. /**
  16. * 当websocket收到文本消息时, 这个方法被调用
  17. * message包含了收到的消息
  18. * 该方法在收到消息后打印消息的内容
  19. * 然后, 它将收到的消息原封不动返回客户端, 这是一种回显机制
  20. * @param session
  21. * @param message
  22. * @throws Exception
  23. */
  24. @Override
  25. protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
  26. System.out.println("收到消息: " + message.getPayload());
  27. //让服务器收到数据之后, 把数据原封不动地返回回去
  28. session.sendMessage(message);
  29. }
  30. /**
  31. * websocket传输过程中出现错误时, 这个方法被调用
  32. * exception包含了异常信息
  33. * 该方法在发生错误时打印一条信息
  34. * @param session
  35. * @param exception
  36. * @throws Exception
  37. */
  38. @Override
  39. public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
  40. System.out.println("连接异常");
  41. }
  42. /**
  43. * 当wesocket连接正常关闭时, 这个方法被调用
  44. * status表示关闭的状态和原因
  45. * 关闭连接时打印一条信息
  46. * @param session
  47. * @param status
  48. * @throws Exception
  49. */
  50. @Override
  51. public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
  52. System.out.println("连接关闭");
  53. }
  54. }

在前端中也是通过类似的方式:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>TestAPI</title>
  7. </head>
  8. <body>
  9. <input type="text" id="message">
  10. <button id="submit">提交</button>
  11. <script>
  12. //创建websocket实例, 并尝试与服务端127.0.0.1:8080进行连接
  13. let websocket = new WebSocket("ws://127.0.0.1:8080/test");
  14. //需要给实例挂载一些回调函数
  15. websocket.onopen = function() {
  16. console.log("连接建立");
  17. }
  18. websocket.onmessage = function(e) {
  19. console.log("收到消息: " + e.data);
  20. }
  21. websocket.onerror = function() {
  22. console.log("连接异常");
  23. }
  24. websocket.onclose = function() {
  25. console.log("连接关闭");
  26. }
  27. //实现点击按钮后, 通过 websocket 发送请求
  28. let input = document.querySelector("#message");
  29. let button = document.querySelector("#submit");
  30. button.onclick = function() {
  31. console.log("发送信息: " + input.value);
  32. websocket.send(input.value);
  33. }
  34. </script>
  35. </body>
  36. </html>

我们来运行一下上面的代码, 观察现象:

当我们打开客户端页面时:

 我们在客户端发送一条信息:ddd

关闭服务器:

可以观察到一次顺利的WebSocket通信, 以后这块会重点使用.

问题: WebSocket和HTTP协议的区别?

1.连接方式: http是无状态的连接; WebSocket是持久连接

2.通信方式: http通过请求-响应的方式来通信; 而WebSocket是服务器主动给客户端响应

3.实时性: 由于http需要不断发送请求才能获取数据, 因此其实时性较低; WebSocket能够由于是全双工, 服务器可以主动给客户端传输数据, 实时性高

4.数据传输速率: http每次传输需要发送完整的Header和body, 传输较慢; WebSocket在第一次连接后以后都是传输很小的数据帧, 传输速率高

5.使用场景: Http一般用于网页浏览中涉及网页渲染这种; WebSocket用于实时性较高的场景如游戏, 在线聊天等.

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号