从零开始写游戏之斗地主-网络通信

在确定了数据结构后,原本是打算直接开始写斗地主的游戏运行逻辑的。但是突然想到我本地写出来之后,也测试不了啊,所以还是先写通信模块了。

基本框架

在Java语言中搞网络通信,那么就得请出Netty这个老演员了。

主要分为两个端:服务器客户端

其中,搭建的代码都是老八股代码了,这里就不展开具体的代码了,有兴趣的可以到Github上看看。

Github代码地址:

服务器:GameServer.java

客户端:GameClient.java

协议选型

搭建好服务器以及客户端后,就要往建立连接的Netty流水线中添加处理器了。

要首先添加的处理器那就是网络协议了,一般来说有以下几种选择:

  1. HTTP:请求-响应模型

请求-响应模型,需要等待响应,实时性低。

  1. WebSocket:全双工

无需二次开发,开箱即用。

  1. 私有协议:想咋弄咋弄,与WebSocket相似

自由度高,但需要自己处理数据的序列化以及安全问题。

最终还是选择了私有协议,因为在最初的构想中,整个斗地主的通信会有两种模式并存。登录以及加入游戏房间等操作时使用阻塞的请求响应模型、游戏过程中则是使用事件驱动的形式。单纯的HTTP以及WebSocket都不能满足我设想的。

明面上选择的理由是不使用Http的请求-响应模型以及需要使用自定义协议用于高性能的游戏通信。(斗地主也要高性能!)

私有协议

选择私有协议后,下一步要做的事情就是制定数据包的格式了。

数据包格式

数据包的前三个字节,这里参照了文件中的魔数(例如Java中class文件的java魔数),数据包的前三个字节就使用了FTL(FightTheLandlord)来做为魔数。

因为在TCP协议传输数据的过程中,会出现粘包、拆包的问题(老八股了)。所以设置完魔数后,之后的四个字节设置成本次数据包中数据字节的长度。紧接着的数据就是序列化后的事件字节了。

数据包格式

Netty编解码器:Codec.java

粘包、拆包处理器:FrameDecoder.java

序列化事件

咱们都知道,网络通信底层传输的都是字节,所以一个对象想要传输给其他的应用,都需要将这个对象序列化成字节数组。

在这一次的序列化框架中,我选择的是Kryo。这个序列化框架的性能较高并且使用起来也很方便。有一点比较特殊,要想使用最好性能时,需要事先声明可能需要序列化的类。

序列化工具类:KryoBuilder.java

数据加密

搭建完通信之后,我简单的测试了一下,发现有个比较明显的安全问题。在Wireshark抓包的过程中,能搞清晰的看到数据包中的数据,所以要在数据传输前对数据包进行加密的处理。

能看到明文的数据

由于是一个游戏服务器,所以不能像普通的聊天服务一样,进行端到端的加密。并且由于是服务器与多个客户端的连接,于是采用了RSA+AES的处理。

密钥交换逻辑:

  1. 服务器生成并发送RSA公钥给客户端。
  2. 客户端生成AES密钥并使用RSA公钥加密,发送给服务器。
  3. 服务器使用RSA密钥解密得到AES密钥,密钥交换完成。

简单的来说就是服务器生成RSA公私钥客户端生成AES密钥

加密后的数据包:

添加加密逻辑后的初始化数据包

AES密钥加密后的登录请求数据包

连接监测

因为是一个游戏,所以对于网络的连接性需要更加敏感。于是在客户端设置了800ms的心跳事件定时任务,每隔800ms发送一个心跳事件给游戏服务器。

为什么不是服务器给客户端发送呢?因为这个定时发送心跳事件需要额外的资源,所以使用客户端最合适了😎

当有心跳数据包发送失败次数达到阈值时,重新尝试连接服务器并重置失败次数。

总结

到了这里,这一篇斗地主的网络通信就差不多写完了,就差往里面塞代码了。其中有一个非常严峻的问题等着我去做一个抉择,咱游戏的界面究竟要用啥技术呢?是Java的GUI呢还是常规的Web端呢?都是有待商榷的,好了,就说到这里了,下一篇文章再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/927921.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Logistic Regression(逻辑回归)、Maximum Likelihood Estimatio(最大似然估计)

Logistic Regression(逻辑回归)、Maximum Likelihood Estimatio(最大似然估计) 逻辑回归(Logistic Regression,LR)逻辑回归的基本思想逻辑回归模型逻辑回归的目标最大似然估计优化方法 逻辑回归…

数据类型.

数据类型分类 数值类型 tinyint类型 以tinyint为例所有数值类型默认都是有符号的,无符号的需要在后面加unsignedtinyint的范围在-128~127之间无符号的范围在0~255之间(类比char) create database test_db; use test_db;建表时一定要跟着写上属性 mysql> creat…

IDEA使用HotSwapHelper进行热部署

目录 前言JDK1.8特殊准备DECVM安装插件安装与配置参考文档相关下载 前言 碰到了一个项目,用jrebel启动项目时一直报错,不用jrebel时又没问题,找不到原因,又不想放弃热部署功能 因此思考能否通过其他方式进行热部署,找…

机器学习算法(六)---逻辑回归

常见的十大机器学习算法: 机器学习算法(一)—决策树 机器学习算法(二)—支持向量机SVM 机器学习算法(三)—K近邻 机器学习算法(四)—集成算法 机器学习算法(五…

【Electron学习笔记(四)】进程通信(IPC)

进程通信(IPC) 进程通信(IPC)前言正文1、渲染进程→主进程(单向)2、渲染进程⇌主进程(双向)3、主进程→渲染进程 进程通信(IPC) 前言 在Electron框架中&…

GateWay使用手册

好的&#xff0c;下面是优化后的版本。为了提高可读性和规范性&#xff0c;我对内容进行了结构化、简化了部分代码&#xff0c;同时增加了注释说明&#xff0c;便于理解。 1. 引入依赖 在 pom.xml 中添加以下依赖&#xff1a; <dependencies><!-- Spring Cloud Gate…

【Go 基础】channel

Go 基础 channel 什么是channel&#xff0c;为什么它可以做到线程安全 Go 的设计思想就是&#xff1a;不要通过共享内存来通信&#xff0c;而是通过通信来共享内存。 前者就是传统的加锁&#xff0c;后者就是 channel。也即&#xff0c;channel 的主要目的就是在多任务间传递…

C# 解决【托管调试助手 “ContextSwitchDeadlock“:……】问题

文章目录 一、遇到问题二、解决办法 一、遇到问题 托管调试助手 “ContextSwitchDeadlock”:“CLR 无法从 COM 上下文 0x56e81e70 转换为 COM 上下文 0x56e81d48&#xff0c;这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows …

Spring AI 框架介绍

Spring AI是一个面向人工智能工程的应用框架。它的目标是将Spring生态系统的设计原则&#xff08;如可移植性和模块化设计&#xff09;应用于AI领域&#xff0c;并推广使用pojo作为AI领域应用的构建模块。 概述 Spring AI 现在(2024/12)已经支持语言&#xff0c;图像&#xf…

使用Grafana K6来测测你的系统负载能力

背景 近期我们有个号称会有很高很高并发的系统要上线&#xff0c;为了测试一下自己开发的系统的负载能力&#xff0c;准备了点海克斯科技&#xff0c;来看看抗不抗的住。 之前笔者写过用Apache JMeter进行压力测试的文章&#xff08;传送门&#x1f449;&#xff1a;https://…

32 从前序与中序遍历序列构造二叉树

32 从前序与中序遍历序列构造二叉树 32.1 从前序与中序遍历序列构造二叉树解决方案 class Solution { public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {return buildTreeHelper(preorder, inorder, 0, 0, inorder.size() - 1)…

【C++boost::asio网络编程】有关异步读写api的笔记

异步读写api 异步写操作async_write_someasync_send 异步读操作async_read_someasync_receive 定义一个Session类&#xff0c;主要是为了服务端专门为客户端服务创建的管理类 class Session { public:Session(std::shared_ptr<asio::ip::tcp::socket> socket);void Conn…

Flutter如何适配RTL

阿拉伯语和希伯来语等是使用的从右到左书写的文字系统。世界上估计有4.22亿人以阿拉伯语做为母语。使用从右至左的人口可以说是更多了。所以对于出海项目来说&#xff0c;是不能忽视的一部分。 RTL可以说是本地化适配中比较麻烦的一项&#xff0c;并没有多语言适配来的简单。RT…

【Django-xadmin】

时间长不用,会忘的系列 1、Django-xadmin后台字段显示处理 主要是修改每个模块下adminx.py文件 代码解释&#xff1a;第1行控制表单字段显示第2行控制列表字段显示第3行控制搜索条件第4行控制过滤条件第5行支持单个或多个字段信息修改第6行列表分页&#xff0c;每页显示多少行…

Pytest --capture 参数详解:如何控制测试执行过程中的输出行为

--capture 选项用于控制测试用例执行过程中标准输出&#xff08;stdout&#xff09;和标准错误输出&#xff08;stderr&#xff09;的捕获行为。 --capture 的选项值&#xff1a; fd&#xff08;默认&#xff09; 捕获文件描述符级别的输出&#xff08;stdout 和 stderr&#x…

整合SSM框架:构建Java Web应用

目录 简介 项目结构 配置文件详解 db.properties mybatis-config.xml spring-mybatis.xml springmvc.xml web.xml pom.xml 整合步骤 为什么这样整合&#xff1f; 简介 SSM框架整合指的是Spring、Spring MVC和MyBatis三个开源框架的整合。这种整合方式在Java Web开发…

Solidity开发智能合约

05-Solidity开发智能合约 0 Solidity和智能合约 Solidity开发可运行的智能合约步骤&#xff1a; 源代码通过编译成字节码&#xff08;Bytecode&#xff09;&#xff0c;同时会产生二进制接口规范&#xff08;ABI&#xff09; 通过交易将字节码部署到以太坊网络&#xff0c;部署…

Java基础之控制语句:开启编程逻辑之门

一、Java控制语句概述 Java 中的控制语句主要分为选择结构、循环结构和跳转语句三大类&#xff0c;它们在程序中起着至关重要的作用&#xff0c;能够决定程序的执行流程。 选择结构用于根据不同的条件执行不同的代码路径&#xff0c;主要包括 if 语句和 switch 语句。if 语句有…

Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架

一、项目构建环境准备 在构建Vue项目之前&#xff0c;需要搭建Node环境以及Vue-CLI脚手架&#xff0c;由于本篇文章为上一篇文章的补充&#xff0c;也是为了给大家分享更为完整的搭建vue项目方式&#xff0c;所以环境准备部分采用Vue教程&#xff5c;搭建vue项目&#xff5c;V…

shell脚本30个案例(五)

前言&#xff1a; 通过一个多月的shell学习&#xff0c;总共写出30个案例&#xff0c;分批次进行发布&#xff0c;这次总共发布了5个案例&#xff0c;希望能够对大家的学习和使用有所帮助&#xff0c;更多案例会在下期进行发布。 案例二十一、系统内核优化 1.问题&#xff1…