Packet
Packet
类用于表示业务数据结构。我们通过继承 Packet
来实现自己的业务数据结构。对于大家而言,可以将 Packet
看作一个普通的 VO(Value Object)对象。
注意:不建议直接使用 Packet
类,而是应该继承它来创建自定义的 Packet。
一个简单的 Packet
可能如下:
import com.litongjava.tio.core.intf.Packet;
/**
* 一个简单的 HelloPacket 示例
*
* 作者:tanyaowu
*/
public class HelloPacket extends Packet {
private static final long serialVersionUID = -172060606924066412L;
public static final int HEADER_LENGTH = 4; // 消息头的长度
public static final String CHARSET = "utf-8";
private byte[] body;
/**
* 获取消息体
*
* @return 消息体的字节数组
*/
public byte[] getBody() {
return body;
}
/**
* 设置消息体
*
* @param body 要设置的消息体字节数组
*/
public void setBody(byte[] body) {
this.body = body;
}
}
可以结合 AioHandler
接口来理解 Packet
的作用:
package com.litongjava.tio.core.intf;
import java.nio.ByteBuffer;
import com.litongjava.tio.core.ChannelContext;
import com.litongjava.tio.core.TioConfig;
import com.litongjava.tio.core.exception.TioDecodeException;
/**
* 定义编码、解码和处理消息包的方法
*
* 作者:tanyaowu
* 日期:2017年10月19日
*/
public interface AioHandler {
/**
* 根据 ByteBuffer 解码成业务需要的 Packet 对象。
* 如果收到的数据不完整,导致解码失败,请返回 null,框架会在下次收到数据时自动拼接之前的数据。
*
* @param buffer 参与本次解码的 ByteBuffer
* @param limit ByteBuffer 的 limit
* @param position ByteBuffer 的 position,不一定是 0
* @param readableLength 本次可读的有效数据长度(limit - position)
* @param channelContext 通道上下文
* @return 解码后的 Packet 对象,若数据不完整则返回 null
* @throws TioDecodeException 解码异常
*/
Packet decode(ByteBuffer buffer, int limit, int position, int readableLength, ChannelContext channelContext) throws TioDecodeException;
/**
* 编码方法
*
* @param packet 要编码的 Packet 对象
* @param tioConfig Tio 配置
* @param channelContext 通道上下文
* @return 编码后的 ByteBuffer
*/
ByteBuffer encode(Packet packet, TioConfig tioConfig, ChannelContext channelContext);
/**
* 处理收到的消息包
*
* @param packet 收到的 Packet 对象
* @param channelContext 通道上下文
* @throws Exception 处理异常
*/
void handler(Packet packet, ChannelContext channelContext) throws Exception;
}
常见的 Packet 实现
以下是一些常见的 Packet
类的内部实现示例,供大家参考。
ByteBufferPacket
package com.litongjava.tio.boot.tcp;
import java.nio.ByteBuffer;
import com.litongjava.tio.core.intf.Packet;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
/**
* 一个使用 ByteBuffer 的 Packet 实现
*/
@NoArgsConstructor
@AllArgsConstructor
public class ByteBufferPacket extends Packet {
private static final long serialVersionUID = 1L;
private ByteBuffer byteBuffer;
/**
* 获取 ByteBuffer
*
* @return ByteBuffer 对象
*/
public ByteBuffer getByteBuffer() {
return byteBuffer;
}
/**
* 设置 ByteBuffer
*
* @param byteBuffer 要设置的 ByteBuffer 对象
*/
public void setByteBuffer(ByteBuffer byteBuffer) {
this.byteBuffer = byteBuffer;
}
}
EncodedPacket
package com.litongjava.tio.core.intf;
/**
* 一个包含原始字节数据的 Packet 实现
*
* 作者:tanyaowu
* 日期:2017年4月1日
*/
public class EncodedPacket extends Packet {
private static final long serialVersionUID = 1014364783783749718L;
private byte[] bytes;
/**
* 构造方法,使用指定的字节数组初始化
*
* @param bytes 原始字节数据
*/
public EncodedPacket(byte[] bytes) {
this.bytes = bytes;
}
/**
* 获取字节数据
*
* @return 字节数组
*/
public byte[] getBytes() {
return bytes;
}
/**
* 设置字节数据
*
* @param bytes 要设置的字节数组
*/
public void setBytes(byte[] bytes) {
this.bytes = bytes;
}
}
通过以上示例,可以更好地理解如何通过继承 Packet
类来实现自定义的业务数据结构,以及在 Tio 框架中如何编码、解码和处理这些数据包。