Netty与SpringBoot的游戏服务器

目录

Netty与SpringBoot的游戏服务器

前言

一、项目整体流程

二、项目启动

1.克隆或下载该项目

2.导入idea,或者上一步用idea导入

3.导入数据库

4、启动redis

5、启动登录和游戏服务器

6、启动客户端操作

三、项目设计概要

1、整合springboot

2、整合google-protobuf

3、order的策略模式

总结


前言

该项目为2017年入职第一家公司时的一个项目,当时仅凭着一腔热血,只身进入公司,也可以不要工资,只要能让我学习到项目经验,当然这不可取,实在是条件比较艰苦。言归正传,当初所使用的技术为mybatis+netty,还未使用到spring,其实是我当时还不会用。最近准备学习微服务和rpc等相关技术,所以又把这个项目掏出来重新复习一下netty了。

项目架构:

springboot-2.1.7

netty-4

fastjson

jedis(连接池)

mybatis

google-protobuf(消息传输协议)

项目亮点:

1、登录服务器与游戏服务器可分离,可在登录服务器做多个游戏服务器地址实现负载均衡

2、通过验证redis中的token判断是否有效登录,如无登录信息则无法进入游戏服务器,使用redis管理房间和大厅,提升IO读写速度,加快服务器响应

3、使用protobuf来最大程度减少网络请求中的时间和空间消耗

4、使用策略模式+线程池对消息做异步处理,提高服务器处理效率


一、项目整体流程

  1. 客户端通过已知的服务器域名/IP进行登录

  2. 登录成功后服务器返回token和uid以及游戏的ip及端口(可以跟登录服务器同一ip),客户端再次连接游戏服务器
  3. 客户端连接成功后发送登录成功的验证请求,同时也是获取大厅信息的请求
  4. 登录状态验证成功后拿到大厅信息,选择进入大厅内的某不同倍率的房间
  5. 进入房间后服务器将返回该房间所有可以进入的座位,需要有座位才可进行游戏(通过座位来对游戏的最大同时响应连接数做限制)
  6. 进入座位后即可准备开始游戏:获取第一组手牌
  7. 观察当前手牌的牌型,保留期望牌型所需的牌,可进行替换,,例如:3,4,5,6,J 前面四张可能组成顺子,则保留前面四张,进行替换
  8. 替换将从准备好的牌组中顺序增加指定张数的牌,与保留的牌组成新的牌型,可以全部保留,则实际不替换,也可全部不保留,则全部从新牌组中抽取
  9. 根据牌型判断最终结果,如果结果有分,则可以进行比倍,比倍将获得更多分数(具体比倍的逻辑有点忘了,随便整了个,如果有会玩这个游戏的可以留言做出修改)
  10. 比倍结束或不比倍之后,刷新改用户的总分数,游戏结束
  11. 正常退出需退出座位再退出房间,或断开连接后服务端将在一定时间后清除用户信息

二、项目启动

1.克隆或下载该项目

Git clone https://gitee.com/pineappleLB/mx-work.git

2.导入idea,或者上一步用idea导入

链接导入idea:file -> new -> Project from Version Control -> Git -> 粘贴上方链接

下载后导入:file -> Open -> 选择到文件位置(选择maven项目)

3.导入数据库

新建数据库`mxsoha`,将mxsoha.sql中的sql语句导入到数据库

4、启动redis

5、启动登录和游戏服务器

可以修改单独从LoginServer中启动,为GameServer提供负载均衡,也可直接启动GameServer登录和游戏一起

6、启动客户端操作


三、项目设计概要

1、整合springboot

@SpringBootApplication
public class GameApplication implements CommandLineRunner {@Autowiredprivate GameServer gameServer;@Autowiredprivate LoginServer loginServer;@Autowiredprivate CommandLoader commandLoader;public static void main(String[] args) {new SpringApplicationBuilder(GameApplication.class).web(WebApplicationType.NONE).run(args);}@Overridepublic void run(String... args) throws Exception {// 依次启动服务器new Thread(loginServer).start();new Thread(gameServer).start();// 加载指令映射commandLoader.loadCommand();}
}

使用CommandLineRunner 接口在spring加载完成后启动nettyServer,

new SpringApplicationBuilder(GameApplication.class).web(WebApplicationType.NONE).run(args);

使用SpringBoot的非Web方式启动,不占用Web端口

2、整合google-protobuf

@Override
protected void initChannel(SocketChannel sc) throws Exception {sc.pipeline()
//              .addLast(new IdleStateHandler(5, 0, 0)).addLast(new ProtobufVarint32FrameDecoder())//给服务器添加编码解码器.addLast(new ProtobufDecoder(BasicProto.BaseMessage.getDefaultInstance())).addLast(new ProtobufVarint32LengthFieldPrepender()).addLast(new ProtobufEncoder())//添加服务端业务处理类.addLast(loginServerHandler);
}

proto文件:

/*请求消息*/
message BaseMessage {int32 order = 1; //命令bytes body = 2; // 消息体
}// 登录请求
message LoginRequest {string name = 1; // 姓名string pass = 2; // 密码
}// 登录返回实体
message LoginResponse {Res res = 1; // 请求返回状态int32 lobbyPort = 2; // 大厅端口string lobbyHost = 3; // 大厅地址User user = 4; // 用户信息
}

登录解析:

@Override
public void doMessage(BasicProto.BaseMessage msg, IOSession session) throws Exception {UserProto.LoginRequest loginRequest = UserProto.LoginRequest.parseFrom(msg.getBody());String name = loginRequest.getName();String pass = loginRequest.getPass();//调用service中的方法验证用户信息,并返回完整的用户信息User u = loginUserService.userLogin(name, pass);// 登录逻辑判断// 省略....
}

添加protobuf的编解码类,以及全局protobuf基类原型,通过proto类的parseForm方法将基类中的实际请求参数转换为指定的类

3、order的策略模式

    private Map<Integer, TCPMessage<?>> handlerMap = new ConcurrentHashMap<>();private final String BASE_PACKAGE = "club.pinea.handler";private final String RESOURCE_PATTERN = "/**/*.class";/*** 加载command对应的处理类*/public void loadCommand() {//spring工具类,可以获取指定路径下的全部类ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();try {String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;Resource[] resources = resourcePatternResolver.getResources(pattern);//MetadataReader 的工厂类MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);for (Resource resource : resources) {//用于读取类信息MetadataReader reader = readerFactory.getMetadataReader(resource);//扫描到的classString classname = reader.getClassMetadata().getClassName();Class<?> clazz = Class.forName(classname);//判断是否有指定主解Head anno = clazz.getAnnotation(Head.class);if (anno != null) {//将注解中的类型值作为key,对应的类作为 value
//                    handlerMap.put(classname, clazz);Object bean = SpringContextUtils.getBean(clazz);if (bean instanceof TCPMessage) {TCPMessage<?> tcpMessage = (TCPMessage<?>) bean;handlerMap.put(anno.value(), tcpMessage);}}}} catch (IOException | ClassNotFoundException e) {}}/*** 获取处理类** @param command* @return*/public TCPMessage getHandler(int command) {return handlerMap.get(command);}

通过ResourcePatternResolver类获取项目中指定包下的类,并判断是否有包含自定义注解,将注解对应的order与消息中的order值对应,即可在netty的channelRead中获取到该次请求消息应该由哪个handler处理,即调用getHandler方法传入baseMessage中的order属性即可

总结

项目地址:https://gitee.com/pineappleLB/mx-work

项目有部分内容未完全完成,仅作为学习框架之余的练手项目,如有兴趣可以自行修改完成,对项目有疑问或建议可以评论留言或者在gitee留言

Netty+SpringBoot搭建游戏服务器(带控制台客户端)相关推荐

  1. 《梦幻西游H5》L inux搭建游戏服务器!

    西游H5 linux 架设教程 准备工具: Termux(安卓) Notepad++ SecureCRT WinSCP 安装宝塔直接运行命令即可. yum install -y wget && ...

  2. 从零开始搭建游戏服务器 第一节 创建一个简单的服务器架构

    目录 引言 技术选型 正文 创建基础架构 IDEA创建项目 添加Netty监听端口 编写客户端进行测试 总结 引言 由于现在java web太卷了,所以各位同行可以考虑换一个赛道,做游戏还是很开心的. ...

  3. php 多人游戏_「谁会是下一个王者农药」云服务器如何搭建游戏服务器?

    手游越来越火了,听听业内人士的分析,他山之石,多多借鉴,那么手游的服务器到底如何搭建的? 从事游戏服务器开发差不多两年时间,两年间参与了不少项目,学到了很多游戏服务器开发技术,参与过几个不同架构的服务 ...

  4. 从零搭建游戏服务器,拢共分几步?

    现代的电子游戏,不管是端游还是手游,网络游戏还是单机游戏,或多或少都会需要一些网络功能.从验证正版,到登录注册,再到多人交互,实时对战,都需要服务器端的支持. 游戏服务器端,是一个长期运行的程序,还要 ...

  5. 从零搭建游戏服务器,编译过程和环境部署教程详解

    现代的电子游戏,不管是端游还是手游,网络游戏还是单机游戏,或多或少都会需要一些网络功能.从验证正版,到登录注册,再到多人交互,实时对战,都需要服务器端的支持. 游戏服务器端,是一个长期运行的程序,还要 ...

  6. 搭建游戏服务器的问题笔记

    1:FTBserver进行数据的传输,FTP服务器可以设置匿名登录或者账号登录,8uftp.需要服务器然后客户端连接 2 : 数据库的建立注意不要占用接口,一般使用3306,在连接其它机器数据库的时候 ...

  7. linux下搭建游戏服务器运行环境

    最近一直只在搭建公司游戏服务器的运行环境. ps背景:  使用java开发,之前一直都是在window环境下开发的,现在要将项目部署到linux环境下 ,所以历程缓慢啊... 说说过程中都遇到啥吧! ...

  8. springboot搭建http2服务器和h2c服务器 h2 的http/https 请求服务器

    HTTP2.0特性 通俗易懂篇:https://www.cnblogs.com/yingsmirk/p/5248506.html 深入了解篇:https://www.jianshu.com/p/67c ...

  9. 《从零开始搭建游戏服务器》Linux开发环境配置

    前言: 之前的开发工作一直是在Windows开发环境下进行的,但是正真发布和外网运营势必要发布到Linux环境下,而且有很多服务端的工具对于Windows系统的兼容性并不是非常完善,就像常用的Dock ...

最新文章

  1. ContentType大全
  2. Unity3D中暂停时的动画及粒子效果实现
  3. Shark集群搭建配置
  4. C和指针之字符串实现my_strrchr(char *str, int ch)的函数
  5. urllib.error.HTTPError: HTTP Error 403: Forbidden
  6. linux判断值相等_Shell字符串比较相等、不相等方法小结【转】
  7. win32开发(图形绘制)
  8. Java并发编程的艺术 记录(三)
  9. php7不解析下载,Centos7 配置apache和php,登陆web提示下载,不解析php文件
  10. H+ HPlus创建新的标签页/选项卡
  11. Steam提示steam需要在线更新 + steam needs to be online to update最全解决方法
  12. 技嘉主板bios设置方法
  13. 4 大话“奇异值”矩阵
  14. U盘量产工具相关知识2
  15. nvidia驱动缓存能清理吗?
  16. 一个毕业设计手机病毒软件查杀
  17. Fastlane使用说明
  18. 机器性能测试与显卡价格报表
  19. 什么是快速连接器?如何选择合适的快速密封接头?
  20. PHP empty()

热门文章

  1. 【android】音乐播放器之UI设计的点点滴滴
  2. 单片机入门(数码管显示0-99)--适合初学者
  3. Linux下使用gcc时conio头文件问题
  4. oracle exp imp 导入 正在跳过表 plsql 导入表 成功终止 数据 被导入
  5. Odaily星球日报与BitUniverse达成战略合作
  6. pip install tkinter:ERROR: Could not find a version that satisfies the requirement tkinter
  7. 从无到有:Latex写英文论文 2
  8. 苹果CMS对接公众号教程
  9. 培训机构借助创客匠人发力线上业务
  10. 通关4级之听力(2021.02.26)