面试题答案
一键面试自定义协议设计关键要素
- 消息头:
- 魔数:用于标识该协议,可防止误解析,例如设置一个固定的4字节魔数
0x12345678
。 - 版本号:便于协议升级,1字节表示版本,如
0x01
代表第1版。 - 消息长度:4字节,记录整个消息(包括头和体)的长度,方便接收端按长度读取完整消息。
- 序列号:4字节,用于标识消息顺序,在文件传输中可用于重组分片。
- 魔数:用于标识该协议,可防止误解析,例如设置一个固定的4字节魔数
- 消息体:
- 文件名:以字符串形式,长度可变,需有长度前缀指明文件名长度。
- 文件内容:二进制数据,长度由消息头中的消息长度减去消息头长度得到。
- 可靠性机制:
- 确认机制:发送方发送消息后等待接收方的确认(ACK),若超时未收到则重发。
- 重传机制:采用定时器,记录消息发送时间,超时未收到ACK则重发,重发次数可设上限。
- 顺序控制:通过序列号保证消息按序接收和处理,接收方缓存乱序消息,按序列号重组。
利用Netty编解码器实现协议
- 编码器(Encoder):
- 继承
MessageToByteEncoder
类。 - 在
encode
方法中,先写入消息头:魔数、版本号、消息长度(先预留4字节位置,后续填充)、序列号。 - 接着写入消息体,先写入文件名长度,再写入文件名,最后写入文件内容。
- 填充消息头中预留的消息长度字段。
- 继承
- 解码器(Decoder):
- 继承
ByteToMessageDecoder
类。 - 在
decode
方法中,首先检查字节数是否够读取消息头(魔数4字节 + 版本号1字节 + 消息长度4字节 + 序列号4字节 = 13字节),不够则返回。 - 读取消息头,解析出消息长度。
- 检查剩余字节数是否够读取消息体,不够则返回。
- 读取消息体,先读取文件名长度,再按长度读取文件名,最后读取文件内容。
- 将解析后的消息封装成自定义的消息对象添加到
out
列表中。
- 继承