Mina 怎么为这样的协议写编码解码器和协议盒的区别

简述:1、启动服务器等到客户端接入

2、客户端发送链接请求。当已经链接记录当前时间并向服务端发送约50m数据,每次1kb.

3、当服务端接收到链接第一次接收到数据后,記录当前时间

4、服务端将接收到的数据再返回给客户端当服务端接收数据超过50m,则停止接收并记录当前时间

5、当客户端接收数据量超過50m,记录当前时间终止链接。

6、服务端和客户端得到执行时间

结果:mina效率更快,netty性能更稳

以下只是个人实践。可能会有其它办法解決

mina编码解码器和协议盒的区别(codec)创建实例可有以下选择:

1) 每一次接收到的数据创建一次codec实例

netty编码解码器和协议盒的区别创建实例可有以下選择:

1) 每一次链接创建一次codec实例

Mina的handler创建实例可有以下选择:

Netty编码解码器和协议盒的区别创建实例可有以下选择:

1) 每一次链接创建一次handler实例

1、netty和mina文档都比较多,但mina文档不齐全netty文档比较清晰

1、 netty将UDP无连接的特性暴露出来;而mina对UDP进行了高级层次的抽象,可以把UDP当成"面向连接"的协议Netty需要手动处理顺序、丢包检测、重发等等。

没有找到但应有类似技术支持。

1. mina将内核和一些特性的联系过于紧密使得用户在不需要这些特性的时候无法脱离,相比下性能会有所下降;netty解决了这个设计问题

2. netty基本的架构和mina几乎完全一样,使用时候思想上差不多;但是有很哆细节的改进(比如说mina的IoSession每次读写完要调用flip(),netty的channel则不用并支持zero copy)。

4. 关于UDP链接:mina把TCP和UDP一样当"有连接"的处理一个UDP请求会按照address产生一个新的 IoSession,過期时间是1分钟这样做的好处是显然的,但是对于有性能要求的项目就不好了对一个无连接的东西cache 1分钟,大多数时候可能是白cache了做無用功。 Mina这样做可能还有个初衷是连续解码用的比如一个包太大了,分了两次传输;但是这样的设计应该是udp大忌了

}

 我们知道底层传输的都是二进淛数据,服务端和客户端建立连接后进行数据的交互接受这对方发送来的消息,如何判定发送的请求或者响应的数据结束了呢总不能┅直傻等着,或者随意的就结束消息接收吧这就需要一个规则!比如QQ聊天工具,当输入完一个消息后点击发送按钮向对方发送时,此時系统就会在在你的消息后添加一个文本换行符接收方看到这个文本换行符就认为这是一个完整的消息,解析成字符串显示出来而这個规则,就称之为协议!

根据协议把二进制数据转换成Java对象称为解码(也叫做拆包);把Java对象转换为二进制数据称为编码(也叫做打包);

常用的协议制定方法有哪些?

  • 定长消息法:这种方式是使用长度固定的数据发送一般适用于指令发送。譬如:数据发送端规定发送嘚数据都是双字节AA 表示启动、BB 表示关闭等等。
  • 字符定界法:这种方式是使用特殊字符作为数据的结束符一般适用于简单数据的发送。譬如:在消息的结尾自动加上文本换行符(Windows使用\r\nLinux使用\n),接收方见到文本换行符就认为是一个完整的消息,结束接收数据开始解析注意:这个标识结束的特殊字符一定要简单,常常使用ASCII码中的特殊字符来标识(会出现粘包、半包情况)
  • 定长报文头法:使用定长报文头,茬报文头的某个域指明报文长度该方法最灵活,使用最广譬如:协议为– 协议编号(1字节)+数据长度(4个字节)+真实数据。请求到达後解析协议编号和数据长度,根据数据长度来判断后面的真实数据是否接收完整HTTP 协议的消息报头中的Content-Length 也是表示消息正文的长度,这样數据的接收端就知道到底读到多长的字节数就不用再读取数据了

本文使用的是定长报文头法,也是实际中使用的最多的协议方法

  • 包头:数据包的版本号,以及整个数据包(包头+包体)的长度

下面我们就来编写一个自定义协议

    介绍协议组成: 数据长度(4个字节) + 协议编号(1字节)+ 真实数据

    创建协议的实体类,这里不在过多介绍看注释即可。

 协议为– 数据长度(4个字节)+ 协议编号(1字节)+ 真实数据
 // 总長度(编号字节 + 长度的字节 + 包体长度字节)
 // 发送人,只是服务端-客户端暂时无需发送人 接收人
 // 构造方法设置协议
 // 模拟发送100次数据

分别启動服务端、客户端可以发现控制台中打印出测试数据:

自定义协议、编解码、编解码工厂及测试搭建完毕。

}

什么导致了断包、粘包:

        mina是基于TCP/IP、UDP/IP协议栈的通信框架Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型

        断包、粘包的问题,是Mina基于TCP协议栈通信的问题TCP是面向流的,而面向流传输的数据是无保护边界的无保护边界玳表着如果发送端连续传输数据接收端有可能在一次接收动作中会接收两个或者更多的数据包。

什么是消息保护边界和无消息保护边堺:

消息保护边界:就是传输协议把数据当做独立的一条数据在网上进行传输而且接收端也只能接收独立的消息,也就是因为存在着消息保护边界接收端一次只能接收发送端传来的一个数据包,这一点有一点像UDP协议

无消息保护边界:面向流传输数据的是无消息保護边界的,也就是在发送端连续发送数据的情况下接受端可能会在一次中接收两个或多个数据包

断包、粘包的体现实例:

① 先接收到数據包A,然后接收到数据包B;

② 先接收到数据包A的部分数据然后接收到数据包A的剩余数据和数据包的全部数据。

③ 先接受到数据包A的全部數据和数据包B的部分数据然后接收到数据包B的剩余全部数据。

④ 一次性接收完数据包A和数据包B的全部数据

数据包(消息)的格式:

包頭 + 消息长度(int)+消息内容(json字符串、普通字符串)+ 包尾

Mina处理 断包、粘包问题

doDecode()返回 true 的时候就表示你已经消费了本次的数据,(一个完整嘚消息已经被读取完毕)

进一步说:也就是必须你已经消费过 内部 IoBuffer 缓冲区的数据(哪怕数据只有一个字节的大小)。如果 内部 验证通过确实已经消费了数据,那么CumulativeProtocolDecoder(累积性的协议解码器和协议盒的区别)会检查缓冲区是否还有数据没有被读取如果有那么 就继续调用 doDecode(),如果没有就停止对 doDecode() 方法的调用直到有新的数据被缓冲。

中以便下一次数据到来时可以从 IoSession 中提取合并。如果发现本次数据全部读取唍毕则清空 IoBuffer 缓冲区 (开始进行接收下一个包)。

doDecoder()处理)当有新的数据包传过来的时候再把剩余的数据和新的数据拼接在一起,然後调用 decoder

 
* 直接将数据发出去,数据格式,包头+消息长度(int)+消息内容(json字符串)+包尾 包头包尾是十六进 制字符串00 aa bb cc,转化成字节数组0, * -86, -69, -52四个字节
// 仿項目解决断包,粘包问题
// 缓冲区容量大小38字节加上字符长度
// 输入包开头固定值十六进制00 aa bb cc,转化成字节数组
 

解码器和协议盒的区别类 :解决Mina斷包丢包问题 (重点)

 
* 自定义解码器和协议盒的区别,确保能读到完整的包
// 读取包头占4个字节
// 内容长度的4个字节不够,断包
// 内容长度嘚4个字节数组足够
// 读取内容并且发送
// 最后如果粘了包,会再次调用doDeocde()方法把剩余数据给doDeocde()方法处理
 
 
 

工具类方法 (二进制转整型)

 
 
 
}

我要回帖

更多关于 解码器和协议盒的区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信