做兼职什么网站最靠谱/app推广接单平台
导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客
上一篇,我们初步把消息handler 注册到了服务中,在进行后续工作之前我们需要再做一些准备工作。
第一:把之前自己管理的bean放到spring中去管理,后面大部分的bean都通过spring来管理。
第二:为了方便路由消费,我们要创建一个消息体方便byte字节数组传输。
Spring
先把spring上下文变量工具整好
SpringContextHelper.java
package com.loveprogrammer.base.factory;import org.springframework.context.ApplicationContext;public class SpringContextHelper {private static ApplicationContext ac;public static void setApplicationContext(ApplicationContext ac) {SpringContextHelper.ac = ac;}public static ApplicationContext getContext() {return ac;}public static Object getBean(String name) {return ac.getBean(name);}public static Object getBean(Class clazz) {return ac.getBean(clazz);}}
CommonBootConfig.java
import com.loveprogrammer.base.factory.SpringContextHelper;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;@Configuration
public class CommonBootConfig implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringContextHelper.setApplicationContext(applicationContext);}
}
修改 NetworkListener.java
@Component
public class NetworkListener implements INetworkEventListener {
修改 TcpMessageStringHandler.java
@Component
public class TcpMessageStringHandler extends SimpleChannelInboundHandler<String> {private static final Logger logger = LoggerFactory.getLogger(TcpMessageStringHandler.class);@Autowiredprivate INetworkEventListener listener;// public TcpMessageStringHandler(INetworkEventListener listener) {
// this.listener = listener;
// }
修改TcpServerStringInitializer.java
public class TcpServerStringInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast("framer",new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));pipeline.addLast("decoder", new StringDecoder());pipeline.addLast("encoder", new StringEncoder());TcpMessageStringHandler handler = (TcpMessageStringHandler) SpringContextHelper.getBean(TcpMessageStringHandler.class);pipeline.addLast(handler);}}
消息封装
创建一个类 StringMessage
package com.loveprogrammer.pojo;import com.alibaba.fastjson2.JSON;/*** @ClassName StringMessage* @Description string类型的请求的请求体* @Author admin* @Date 2024/1/31 10:35* @Version 1.0*/
public class StringMessage {/**** topicId 路由主键对应class* tagId 路由副健,对应method* statusC内容的长ode主要是返回内容是告诉客户端消息的状态,成功为1,其他不同的错误使用不同的错误码* length是度,内容的长度是不可控制的,所以使用一个长度进行定义* body是具体的内容*/private int topicId;private int tagId;private int statusCode;private int length;private String body;public StringMessage() {}// public StringMessage(short messageId) {
// this.messageId = messageId;
// }public static StringMessage create(int topicId,int tagId) {StringMessage stringMessage = new StringMessage();stringMessage.setTopicId(topicId);stringMessage.setTagId(tagId);return stringMessage;}public static StringMessage create(String origin) {StringMessage stringMessage = JSON.parseObject(origin, StringMessage.class);return stringMessage;}public static StringMessage create(int length, int topicId,int tagId , int statusCode, String content) {return new StringMessage(length, topicId, tagId, statusCode, content);}private StringMessage(int length, int topicId,int tagId, int statusCode, String body) {this.length = length;this.topicId = topicId;this.tagId = tagId;this.statusCode = statusCode;this.body = body;}public int getTopicId() {return topicId;}public void setTopicId(int topicId) {this.topicId = topicId;}public int getTagId() {return tagId;}public void setTagId(int tagId) {this.tagId = tagId;}public int getStatusCode() {return statusCode;}public void setStatusCode(int statusCode) {this.statusCode = statusCode;}public int getLength() {return length;}public void setLength(int length) {this.length = length;}public String getBody() {return body;}public void setBody(String body) {this.body = body;}@Overridepublic String toString() {return "StringMessage{" + "messageId=" + topicId + ", statusCode=" + statusCode + ", length=" + length+ ", body='" + body + '\'' + '}';}
}
创建两个编解码类
MessageDecoder.java
package com.loveprogrammer.codec;import com.loveprogrammer.constants.ConstantValue;
import com.loveprogrammer.pojo.StringMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;/*** @ClassName MessageDecoder* @Description 消息解码器* @Author admin* @Date 2024/1/31 10:43* @Version 1.0*/
public class MessageDecoder extends LengthFieldBasedFrameDecoder {//判断传送客户端传送过来的数据是否按照协议传输,头部信息的大小应该是 int+int+int = 4+4+4 = 12private static final int HEADER_SIZE = 12;private int topicId;private int tagId;private int statusCode;private int length;private String body;/***** @param maxFrameLength 解码时,处理每个帧数据的最大长度* @param lengthFieldOffset 该帧数据中,存放该帧数据的长度的数据的起始位置* @param lengthFieldLength 记录该帧数据长度的字段本身的长度* @param lengthAdjustment 修改帧数据长度字段中定义的值,可以为负数* @param initialBytesToStrip 解析的时候需要跳过的字节数* @param failFast 为true,当frame长度超过maxFrameLength时立即报TooLongFrameException异常,为false,读取完整个帧再报异常*/public MessageDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);}@Overrideprotected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {if(in == null){return null;}if(in.readableBytes() < HEADER_SIZE) {throw new Exception("可读信息段比头部信息都小");}// 注意在读的过程中,readIndex的指针也在移动topicId = in.readInt();tagId = in.readInt();statusCode = in.readInt();length = in.readInt();if(in.readableBytes() < length) {throw new Exception("body获取长度" + length + ",实际长度没有达到");}ByteBuf buf = in.readBytes(length);byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);body = new String(req, ConstantValue.PROJECT_CHARSET);StringMessage stringMessage = StringMessage.create(length, topicId, tagId, statusCode, body);return stringMessage;}
}
MessageEncoder.java
package com.loveprogrammer.codec;import com.loveprogrammer.constants.ConstantValue;
import com.loveprogrammer.pojo.StringMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;import java.nio.charset.Charset;/*** @ClassName MessageEncoder* @Description 消息编码器* @Author admin* @Date 2024/1/31 10:40* @Version 1.0*/
public class MessageEncoder extends MessageToByteEncoder<StringMessage> {@Overrideprotected void encode(ChannelHandlerContext ctx, StringMessage msg, ByteBuf out) throws Exception {if(null == msg) {throw new Exception("msg is null");}String body = msg.getBody();byte[] bodyBytes = body.getBytes(Charset.forName(ConstantValue.PROJECT_CHARSET));out.writeInt(msg.getTopicId());out.writeInt(msg.getTagId());out.writeInt(msg.getStatusCode());out.writeInt(bodyBytes.length);out.writeBytes(bodyBytes);}
}
下一章我们来实现byte数组传输数据
上一篇:从零开始手写mmo游戏从框架到爆炸(六)— 消息处理工厂-CSDN博客
全部源码详见:
gitee : eternity-online: 多人在线mmo游戏 - Gitee.com
分支:step-06
相关文章:

从零开始手写mmo游戏从框架到爆炸(七)— 消息封装
导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客 上一篇,我们初步把消息handler 注册到了服务中,在进行后续工作之前我们需要再做一些准备工作。 第一:把之前自己管理的bean放到spring中…...

从Unity到Three.js(画线组件line)
JavaScript 0基础,只是照着官方文档临摹了下,之后有时间再进行细节学习和功能封装。 import * as THREE from three; //引入threejsconst renderer new THREE.WebGLRenderer();//创建渲染器 //设置渲染范围,当前撑满全屏,屏幕左上角是&…...

LCP 30. 魔塔游戏 - 力扣(LeetCode)
题目描述 小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1。每个房间的补血道具/怪物对于血量影响记于数组 nums,其中正数表示道具补血数值,即血量增加对应数值;负数表示怪物造成伤害值,即血量减…...

数据结构——单向链表和双向链表的实现(C语言版)
目录 前言 1. 链表 1.1 链表的概念及结构 1.2 链表的分类 2. 单链表接口实现 2.1 数据结构设计与接口函数声明 2.2 创建结点,打印,查找 2.3 尾插,头插,尾删,头删 2.4 插入或删除 2.4.1在指定位置后 2.4.2在…...

TCP和UDP相关问题(重点)(4)——4.使用TCP的协议有哪些?使用UDP的协议有哪些?
4.使用TCP的协议有哪些?使用UDP的协议有哪些? 使用TCP的协议有:HTTP3.0之前的HTTP协议、HTTPS、FTP、SMTP、SSH... 使用UDP的协议有:HTTP3.0、DNS、DHCP......

Python进阶--爬取美女图片壁纸(基于回车桌面网的爬虫程序)
目录 一、前言 二、爬取下载美女图片 1、抓包分析 a、分析页面 b、明确需求 c、抓包搜寻 d、总结特点 2、编写爬虫代码 a、获取图片页网页源代码 b、提取所有图片的链接和标题 c、下载并保存这组图片 d、 爬取目录页的各种类型美女图片的链接 e、实现翻页 三、各…...

[office] excel如何计算毛重和皮重的时间间隔 excel计算毛重和皮重时间间隔方法 #笔记#学习方法
excel如何计算毛重和皮重的时间间隔 excel计算毛重和皮重时间间隔方法 在日常工作中经常会到用excel,有时需要计算毛重和皮重的时间间隔,具体的计算方式是什么,一起来了解一下吧 在日常工作中经常会到用excel,在整理编辑过磅数据…...

Pandas 对带有 Multi-column(多列名称) 的数据排序并写入 Excel 中
Pandas 从Excel 中读取带有 Multi-column的数据 正文 正文 我们使用如下方式写入数据: import pandas as pd import numpy as npdf pd.DataFrame(np.array([[10, 2, 0], [6, 1, 3], [8, 10, 7], [1, 3, 7]]), columns[[Number, Name, Name, ], [col 1, col 2, co…...

如何为Kafka加上账号密码(一)
Kafka认证基本概念 一直以来,我们公司内网的Kafka集群都是在裸奔,只要知道端口号,任何人都能连上集群操作一番。直到有个主题莫名消失,才引起我们的警觉,是时候该考虑为它添加一套认证策略了。 认证和授权就是一对孪生…...

Elasticsearch的Index Lifecycle Management(ILM)
Elasticsearch的Index Lifecycle Management(ILM)功能提供了一种自动化管理索引生命周期的方式。ILM使得用户可以基于特定的条件(如索引的年龄、大小等)来自动执行如回滚、删除等操作,进而优化存储和提高查询性能。ILM…...

2、学习 Nacos 注册中心
学习 Nacos 注册中心 一、使用Nacos作为注册中心1、父pom.xml文件配置SpringCloudAlibaba的dependency-management依赖2、在微服务中添加Nacos客户端依赖3、配置Nacos服务地址 二、服务的分级存储模型1、配置实例的集群属性2、权重配置 三、命名空间 一、使用Nacos作为注册中心…...

Java 如何操作 nginx 服务器上的文件?
随着Java技术的不断发展,越来越多的开发人员开始使用Java来操作服务器上的文件。其中,如何操作nginx服务器上的文件也是许多Java开发人员所关注的重点之一。本文将介绍Java操作nginx服务器上文件的基本方法。 一、使用Java的File类 Java的File类可以用…...

时序预测 | MATLAB实现基于CNN-GRU-AdaBoost卷积门控循环单元结合AdaBoost时间序列预测
时序预测 | MATLAB实现基于CNN-GRU-AdaBoost卷积门控循环单元结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于CNN-GRU-AdaBoost卷积门控循环单元结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于CNN-GRU-AdaBo…...

中创ET4410 台式LCR数字电桥 简单开箱测评
最近买了一台LCR电桥,完善一下自己实验室的设备,选了中创ET4410,这款性价比高一点。 1199元在PDD买的,好像胜利的VC4090C也是找中创代工的。 ET4410介绍 本系列LCR数字电桥是采用自动平衡电桥原理设计的元件参数分析仪…...

格式化dingo返回内容
dingo api返回的内容中添加code 和 message ,保持与异常返回的内容格式相一致。 失败会存在code 和 message ,我们只需要关注成功的情况 非分页返回,可以创建一个父类controller,通过调用sucess方法来返回 class Controller ext…...

QGIS编译(跨平台编译)之四十六:minizip编译(Windows、Linux、MacOS环境下编译)
文章目录 一、minizip介绍二、minizip下载三、Linux下编译四、MacOS下编译五、Windows下编译一、minizip介绍 Minizip 是一个用于处理 ZIP 文件的开源库,它基于 zlib 库构建。zlib 是一个广泛使用的、免费的、开源的压缩库,提供数据压缩和解压缩功能。Minizip 扩展了 zlib 的…...

MySQL进阶查询篇(1)-索引的类型与创建
MySQL数据库索引是提高查询效率的重要手段之一。索引是一种特殊的数据结构,用于快速定位数据。通过创建索引,可以大大提高查询性能,减少数据库的IO操作。 MySQL数据库支持多种不同类型的索引,常用的索引类型包括: B-…...

【STL】list模拟实现
vector模拟实现 一、接口大框架函数声明速览二、结点类的模拟实现1、构造函数 三、迭代器类的模拟实现1、迭代器类存在的意义2、迭代器类的模板参数说明3、构造函数4、运算符的重载(前置和后置)(1)前置(2)后…...

常用的文件系统、存储类型小整理
最近接触到了五花八门的文件系统、存储类型,名词听得头大,趁假期整理学习一番~ 名称OSSFastDFSJuiceFSCIFSCephFSEFSNFS全称Object Storage Service (对象存储服务)Fast Distributed File System (快速分布式文件系统)Juice File System (Juice 文件系统…...

Java写标准输出进度条
学Java这么久了,突发奇想写一个 进度条 玩玩,下面展示一下成功吧! Java代码实现如下 public class ProcessBar {public static void main(String[] args) {//进度条StringBuilder processBarnew StringBuilder();//进度条长度int total100;/…...

leetcode 算法 69.x的平方根(python版)
需求 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。 示例 1&#…...

【golang】24、go get 和 go mod:indrect 与 go mod tidy
文章目录 go get 会执行如下操作: 操作 go.mod 文件(add、update、remove)下载依赖到 $GOPATH/pkg/mod 中若已安装,则更新该包,到最新版本 试验前置准备:首先删除已下载的依赖,rm -rf $GOPATH…...

AI算法工程师-非leetcode题目总结
AI算法工程师-非leetcode题目总结 除了Leetcode你还需要这些实现nms旋转矩形IOU手动实现BN手动实现CONV实现CrossEntropyLoss 除了Leetcode你还需要这些 希望大家留言,我可以进行补充。持续更新~~~ 实现nms import numpy as np def nms(dets, threshold):x1 dets…...

2.6:冒泡、简选、直插、快排,递归,宏
1.冒泡排序、简单选择排序、直接插入排序、快速排序(升序) 程序代码: 1 #include<stdio.h>2 #include<string.h>3 #include<stdlib.h>4 void Bubble(int arr[],int len);5 void simple_sort(int arr[],int len);6 void insert_sort(int arr[],in…...

FastDFS安装并整合Openresty
FastDFS安装并整合Openresty 一、安装环境准备【CentOS7.9】二、FastDFS--tracker安装2.1.下载fastdfs2.2.FastDFS安装环境2.3.安装FastDFS依赖libevent库2.4.安装libfastcommon2.5.安装 libserverframe 网络框架2.6.tracker编译安装2.7.安装之后文件目录介绍2.8.错误处理2.9.配…...

93 log4j-slf4j-impl 搭配上 log4j-to-slf4j 导致的 StackOverflow
前言 呵呵 最近想要 做一个 mongo 低版本的客户端读取高版本的服务端传递过来的数据造成的一个错误的时候, 出现了这样的问题 引入了 mongo-java-driver 之后, 使用相关 api 的时候会触发 com.mongo.internal.connection.BaseCluser 的初始化, 其依赖的 Loggers 间接的依赖…...

客户端会话技术-Cookie
一、会话技术 1.1 概述 会话:一次会话中包含多次**请求和响应** 一次会话:浏览器第一次给服务器资源发送请求,此时会话建立,直到有一方断开为止 会话的功能:在一次会话的范围内的多次请求间,共享数据 …...

rsa加密登录解决方案
1.问题 账密登录方式中用户输入密码后,把账号、密码通过http传输到后端进行校验,然而密码属于敏感信息,不能以明文传输,否则容易被拦截窃取,因此需要考虑如何安全传输密码 2.解决方案 使用rsa加密方式,r…...

速盾:海外服务器用了cdn还是卡怎么办
海外服务器使用CDN卡顿问题的解决办法 在如今互联网高速发展的时代,海外服务器成为了许多企业和个人用户的首选,因为它能够提供更高的带宽和更稳定的网络连接。然而,尽管海外服务器在网络性能方面表现出色,但在使用过程中仍然可能…...

[python-opencv] PNG 裁切物体
拿到一组图PNG的图,边缘有点太宽了,需要裁切一下,为了这个需求,简单复习一下基本语法。 1. 读取PNG的4个通道 image cv.imread(image_path, cv.IMREAD_UNCHANGED) 附参数说明: IMREAD_UNCHANGED -1 返…...