当前位置: 首页 > news >正文

局域网建设网站工具建设公司网站开发方案

局域网建设网站工具,建设公司网站开发方案,微信提示WordPress登录,北京网站建设怎么样序列化的作用及自定义协议序列化的重要性大小对比效率对比自定义协议序列化数据结构自定义编码器自定义解码器安全性验证NettyClientNettyServerNettyClientTestHandlerNettyServerTestHandler结果上一章已经说了怎么解决沾包和拆包的问题#xff0c;但是这样离一个成熟的通信… 序列化的作用及自定义协议序列化的重要性大小对比效率对比自定义协议序列化数据结构自定义编码器自定义解码器安全性验证NettyClientNettyServerNettyClientTestHandlerNettyServerTestHandler结果上一章已经说了怎么解决沾包和拆包的问题但是这样离一个成熟的通信还是有一点距离我们还需要让服务端和客户端使用同一个语言来沟通要不然一个讲英文一个讲中文两个都听不懂岂不是很尴尬这种语言就叫协议。Netty自身就支持很多种协议比如Http、Websocket等等但如果用来作为自己的RPC框架通常会自定义协议所以这也是本文的重点 序列化的重要性 在说协议之前我们需要先知道什么是序列化序列化是干嘛的 我们要知道数据在传输的过程中是以0和1的形式传输的而把对象转化成二进制的过程就叫序列化将二进制转化为对象的过程就叫反序列化。 为什么要说这个很重要呢因为序列化和反序列化是需要耗时的而序列化后的字节大小也会影响到传输的效率所以选对一种高效的序列化方式是非常之重要的下面我们以JDK自带的序列化和我们常用的JSON序列化来做一个对比序列化后大小的对比、序列化效率的对比 大小对比 我们先准备一个实体类SerializeTestVO实现Serializable 接口 public class SerializeTestVO implements Serializable {private Integer id;private String name;private Integer age;private Integer sex;private Integer bodyWeight;private Integer height;private String school;//Set、get方法省略 }测试方法 public static void main(String[] args) throws IOException {// 普普通通的实体类SerializeTestVO serializeTestVO new SerializeTestVO();serializeTestVO.setAge(18);serializeTestVO.setBodyWeight(120);serializeTestVO.setHeight(180);serializeTestVO.setId(10000);serializeTestVO.setName(张三);serializeTestVO.setSchool(XXXXXXXXXXXX);// JDK序列化ByteArrayOutputStream byteArrayOutputStream new ByteArrayOutputStream();ObjectOutputStream objectOutputStream new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(serializeTestVO);objectOutputStream.flush();objectOutputStream.close();System.out.println(JDK 序列化大小: (byteArrayOutputStream.toByteArray().length));byteArrayOutputStream.close();//JSON序列化System.out.println(JSON 序列化大小: JSON.toJSONString(serializeTestVO).getBytes().length); }结果 可以看到序列化后大小相差了好几倍这也意味着传输效率的几倍 效率对比 实体类保持不变我们序列化300W次看看结果 public static void main(String[] args) throws IOException {SerializeTestVO serializeTestVO new SerializeTestVO();serializeTestVO.setAge(18);serializeTestVO.setBodyWeight(120);serializeTestVO.setHeight(180);serializeTestVO.setId(10000);serializeTestVO.setName(张三);serializeTestVO.setSchool(XXXXXXXXXXXX);long start System.currentTimeMillis();for (int i 0; i 3000000; i) {ByteArrayOutputStream byteArrayOutputStream new ByteArrayOutputStream();ObjectOutputStream objectOutputStream new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(serializeTestVO);objectOutputStream.flush();objectOutputStream.close();byte[] bytes byteArrayOutputStream.toByteArray();byteArrayOutputStream.close();}System.out.println(JDK 序列化耗时 (System.currentTimeMillis() - start));long start1 System.currentTimeMillis();for (int i 0; i 3000000; i) {byte[] bytes JSON.toJSONString(serializeTestVO).getBytes();}System.out.println(JSON 序列化耗时 (System.currentTimeMillis() - start1));}结果 几乎6倍的差距结合序列化后的大小综合来看选择一种好的序列化方式是多么的重要 自定义协议 其实到现在我们已经掌握了自定义协议里面最关键的几个点了序列化、数据结构、编解码器我们一个一个来 序列化 直接采用我们常用且熟悉的JSON序列化 数据结构 我们设置为消息头和消息体结构如下 消息头包含开始标志、时间戳、消息体长度 消息体包含通信凭证、消息ID、消息类型、消息 实体类如下 Data public class NettyMsg {private NettyMsgHead msgHeadnew NettyMsgHead();private NettyBody nettyBody;public NettyMsg(ServiceCodeEnum codeEnum, Object msg){this.nettyBodynew NettyBody(codeEnum, msg);} }Data public class NettyMsgHead {// 开始标识private short startSign (short) 0xFFFF;// 时间戳private final int timeStamp;public NettyMsgHead(){this.timeStamp(int)(DateUtil.current() / 1000);} }Data public class NettyBody {// 通信凭证private String token;// 消息IDprivate String msgId;// 消息类型private short msgType;// 消息 这里序列化采用JSON序列化// 所以这个msg可以是实体类的msg 两端通过消息类型来判断实体类类型private String msg;public NettyBody(){}public NettyBody(ServiceCodeEnum codeEnum,Object msg){this.token; // 鉴权使用this.msgId; // 拓展使用this.msgTypecodeEnum.getCode();this.msg JSON.toJSONString(msg);} } 消息类型枚举 JsonFormat(shape JsonFormat.Shape.OBJECT) public enum ServiceCodeEnum {TEST_TYPE((short) 0xFFF1, 测试);private final short code;private final String desc;ServiceCodeEnum(short code, String desc) {this.code code;this.desc desc;}public short getCode() {return code;}}自定义编码器 编码器的作用就是固定好我们的数据格式无需在每次发送数据的时候还需要去对数据进行格式编码 public class MyNettyEncoder extends MessageToByteEncoderNettyMsg {Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, NettyMsg msg, ByteBuf out) throws Exception {// 写入开头的标志out.writeShort(msg.getMsgHead().getStartSign());// 写入秒时间戳out.writeInt(msg.getMsgHead().getTimeStamp());byte[] bytes JSON.toJSON(msg.getNettyBody()).toString().getBytes();// 写入消息长度out.writeInt(bytes.length);// 写入消息主体out.writeBytes(bytes);} }自定义解码器 解码器的第一个作用就是解决沾包和拆包的问题第二个作用就是对数据有效性的校验比如数据协议是否匹配、数据是否被篡改、数据加解密等等 所以我们直接继承LengthFieldBasedFrameDecoder类重写decode方法利用父类来解决沾包和拆包问题自定义来解决数据有效性问题 public class MyNettyDecoder extends LengthFieldBasedFrameDecoder {// 开始标记private final short HEAD_START (short) 0xFFFF;public MyNettyDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {super(maxFrameLength, lengthFieldOffset, lengthFieldLength);}public MyNettyDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip);}public MyNettyDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);}public MyNettyDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {super(byteOrder, maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);}Overrideprotected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {// 经过父解码器的处理 我们就不需要在考虑沾包和半包了// 当然想要自己处理沾包和半包问题也不是不可以ByteBuf decode (ByteBuf) super.decode(ctx, in);if (decode null) {return null;}// 开始标志校验 开始标志不匹配直接 过滤此条消息short startIndex decode.readShort();if (startIndex ! HEAD_START) {return null;}// 时间戳int timeIndex decode.readInt();// 消息体长度int lenOfBody decode.readInt();// 读取消息byte[] msgByte new byte[lenOfBody];decode.readBytes(msgByte);String msgContent new String(msgByte);// 将消息转成实体类 传递给下面的数据处理器return JSON.parseObject(msgContent, NettyBody.class);} }安全性 上述的协议里面我只预留了三种简单的校验一个是开始标识二是消息凭证三是时间戳实时上这太简单了下面我说几种可以加上去拓展的 消息整体加密消息头添加一个加密类型客户端和服务端都内置几种加解密手段在发送消息的时候随机一种加密方式对加密类型、消息长度以外的其他内容加密接收的时候再解密但是要注意加密后不能影响沾包和拆包的处理 消息体加密添加结束标识放入消息体和上述方式类似但是是对消息体中的内容再次加密可和上述方式结合形成二次加密 时间戳可以对长时间才接收到的消息拒收或者要求重发根据消息ID 加签和验签对具体的消息加签和验签防止篡改 凭证这个很熟悉了就比如登录凭证 复杂格式上述的数据格式还是过于简单实际可以整了更加复杂 验证 主体代码呢还是之前的我们改动几个地方 NettyClient 解码器是继承的LengthFieldBasedFrameDecoder所以参数也一样不懂的看一下上一篇 NettyServer NettyClientTestHandler 发送100次是为了验证沾包和拆包发送不同的开始标志是为了验证接收的时候是否有过滤无效数据 NettyServerTestHandler 有了编码器发送可以直接发送实体类有了解码器我们可以直接用实体类接收数据因为解码器里面往下传递的是过滤了消息头的实体类 结果 一共接收到了50条消息而且都是偶数消息说明无效消息被过滤了也没有沾包和拆包
http://www.dnsts.com.cn/news/251961.html

相关文章:

  • 沈阳地区精神文明建设网站网站建设工作部署会
  • 12380网站建设的意见建议wordpress图片 高清
  • 网站开发页面设计报价十大app软件下载入口
  • 成熟的网站怎么做seo推广手机怎样创建网站
  • 郑州众诚建设监理有限公司网站个人网站设计理念
  • 咸阳网站建设专业公司自己的wordpress
  • 制作简单门户网站步骤旅游网站建设策划书范文
  • 58同城 网站建设电子商务网站建设与管理课程论文
  • 网站上传的图片怎么做的清晰品牌推广渠道
  • 用什么l软件做网站了网站备案 企业
  • 高新区网站建设 意义网站优化排名易下拉软件
  • 一般在百度做网站多少钱济南建网站的网站
  • 天津哪里可以做网站品牌建设年 启动
  • 最简单的制作网站深圳网站设计服务公
  • 用canvas做网站河南省建设劳动学会网站
  • 关于网站开发的会议纪要长沙做医院的网站建设
  • 怎样设计一个网站平台淘宝做标题网站
  • 网站建设可行性的分析wordpress比较好的建议
  • 杭州响应式网站教育局网站建设方案
  • 做签名照的网站韩国手做配件网站
  • 建设部职称证书查询官方网站软件开发公司好的有哪些
  • 优化好的网站做企业网站效果图案例网站
  • 商丘网站建设略奥网安徽省建设监理协会 旧网站
  • 男女直接做视频教学视频网站在百度怎么建自己的网站
  • 手机网站怎样做新闻发布网站模板
  • 线上网站怎么做网络舆情工作总结报告
  • 电力建设工程最好的网站网站26个页面收费
  • 求职网站建设方案网站所有权 备案
  • 沧州建设银行招聘网站一等一网站
  • 渭南网站建设wifi微信公众号的子菜单网页怎么制作