如何解析Netty中的各种对象(java)?
How to parse various objects in Netty(java)?
我使用 netty,我想将各种对象从客户端发送到服务器,反之亦然。
我在客户端和服务器上创建了相同的解码器和编码器 class;
解码器:
public class UserInfoDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
...
list.add(new UserInfo(...))
}
}
编码器:
public class UserInfoEncoder extends MessageToByteEncoder<UserInfo> {
@Override
protected void encode(ChannelHandlerContext ctx, UserInfo msg, ByteBuf out) {
...
out.writeBytes(...);
}
这是我的服务器 initChannel 方法:
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
p.addLast(
// new ObjectEncoder(),
// new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
new UserInfoDecoder(),
new UserInfoEncoder(),
new ObjectEchoServerHandler());
}
服务器处理程序中有一个方法 channelRead class
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
...
}
如何区分客户端发送的对象?
例如现在我只有 "UserInfo" class,我可以将 channelRead 中的 "Object msg" 转换为 "UserInfo",但我也想发送 "UsersCar" 对象,例如,如何区分按类型发送的对象?
按照当前的实施方式,实现此目的的最简单方法是在通过通道发送编码字节之前向编码字节添加 'magic byte' 前缀。
public class UserInfoEncoder extends MessageToByteEncoder<UserInfo> {
@Override
protected void encode(ChannelHandlerContext ctx, UserInfo msg, ByteBuf out) {
final int USER_BYTE = 0;
out.writeBytes(USER_BYTE);
out.writeBytes(msg.toBytes());
}
然后在服务器端,当消息被解码时,检查这个魔法字节并根据读取的值分配合适的解码器。
例如。如果第一个未解码字节的值为 0,则使用 UserInfo 解码器。如果第一个未解码字节的值为1,则使用UsersCar解码器。
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final ByteBuf message = (ByteBuf) msg;
final byte magicByte= message.getByte(0);
if(magicByte == 0){
new UserInfoDecoder().decode(message);
}else if {
....
}
}
不是最简洁的解决方案,但却是最简单的。
注意:这是假设您使用的处理程序正在扩展 ChannelInboundHandlerAdapter
让您了解 Netty 的好例子 encoding/decoding:http://shengwangi.blogspot.ie/2016/03/netty-tutorial-hello-world-example.html
我使用 netty,我想将各种对象从客户端发送到服务器,反之亦然。
我在客户端和服务器上创建了相同的解码器和编码器 class;
解码器:
public class UserInfoDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
...
list.add(new UserInfo(...))
}
}
编码器:
public class UserInfoEncoder extends MessageToByteEncoder<UserInfo> {
@Override
protected void encode(ChannelHandlerContext ctx, UserInfo msg, ByteBuf out) {
...
out.writeBytes(...);
}
这是我的服务器 initChannel 方法:
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
p.addLast(
// new ObjectEncoder(),
// new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
new UserInfoDecoder(),
new UserInfoEncoder(),
new ObjectEchoServerHandler());
}
服务器处理程序中有一个方法 channelRead class
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
...
}
如何区分客户端发送的对象? 例如现在我只有 "UserInfo" class,我可以将 channelRead 中的 "Object msg" 转换为 "UserInfo",但我也想发送 "UsersCar" 对象,例如,如何区分按类型发送的对象?
按照当前的实施方式,实现此目的的最简单方法是在通过通道发送编码字节之前向编码字节添加 'magic byte' 前缀。
public class UserInfoEncoder extends MessageToByteEncoder<UserInfo> {
@Override
protected void encode(ChannelHandlerContext ctx, UserInfo msg, ByteBuf out) {
final int USER_BYTE = 0;
out.writeBytes(USER_BYTE);
out.writeBytes(msg.toBytes());
}
然后在服务器端,当消息被解码时,检查这个魔法字节并根据读取的值分配合适的解码器。 例如。如果第一个未解码字节的值为 0,则使用 UserInfo 解码器。如果第一个未解码字节的值为1,则使用UsersCar解码器。
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final ByteBuf message = (ByteBuf) msg;
final byte magicByte= message.getByte(0);
if(magicByte == 0){
new UserInfoDecoder().decode(message);
}else if {
....
}
}
不是最简洁的解决方案,但却是最简单的。
注意:这是假设您使用的处理程序正在扩展 ChannelInboundHandlerAdapter
让您了解 Netty 的好例子 encoding/decoding:http://shengwangi.blogspot.ie/2016/03/netty-tutorial-hello-world-example.html