为什么Netty需要编解码器
网络编程就是意味着:两个服务器要进行数据结构化通信。然而通信的数据就是流。有了编码器和解码器就可以很方便直观实现数据结构化通信
netty默认了编解码器
StringDecoder、StringEncoder 等等
数据流向图
源代码地址在下面
上代码
代码结构
Client
public class Client {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup workerEvent = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerEvent)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,128) // 设置线程队列
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingEncoder());
socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingDecoder());
socketChannel.pipeline().addLast(new ClientHandler()); // 自定义的server处理器
}
});
ChannelFuture connect = bootstrap.connect("127.0.0.1", 9999).sync();
connect.channel().closeFuture().sync();
workerEvent.shutdownGracefully(); // 关闭
}
}
ClientHandler
public class ClientHandler extends ChannelInboundHandlerAdapter {
// 当通道就绪时,会触发 往服务器发送数据
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("client ctx=-------------"+ctx);
// 往服务器发送数据
for (int i = 0, size = 50; i < size; i++) {
ReqData rd = new ReqData();
rd.setId(" "+i);
rd.setName("我是消息"+i);
rd.setRequestMessage("内容"+i);
ctx.writeAndFlush(rd);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try{
RespData data = (RespData) msg;
System.out.println("输出服务器端响应内容:" + data.getId());
System.out.println("输出服务器端响应内容:" + data.getName());
System.out.println("输出服务器端响应内容:" + data.getRequestMessage());
}finally {
ReferenceCountUtil.release(msg);
}
}
}
Marshalling编解码器
/**
* 功能描述:Marshalling编解码器
*
* @author Songxianyang
* @date 2024-01-28 16:05
*/
public final class MarshallingCodec {
/**
* 创建Jboss Marshalling解码器
*
* @return MarshallingDecoder
*/
public static MarshallingDecoder buildMarshallingDecoder() {
//首先通过Marshalling工具类的方法获取Marshalling实例对象,参数serial标识创建的是java序列化工厂
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
//创建MarshallingConfiguration对象,配置版本号为5
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
//根据marshallerFactory和configuration创建provider
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//构建Netty的MarshallingDecoder对象,俩参数分别为provider和单个消息序列化后的最大长度
return new MarshallingDecoder(provider, 1024 * 1024);
}
/**
* 创建Jboss Marshalling编码器MarshallingEncoder
*
* @return MarshallingEncoder
*/
public static MarshallingEncoder buildMarshallingEncoder() {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
//构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
return new MarshallingEncoder(provider);
}
}
Client发送到Server请求数据
/**
* 功能描述:Client发送到Server请求数据
*
* @author Songxianyang
* @date 2024-01-28 16:00
*/
@Data
public class ReqData implements Serializable {
private String id;
private String name;
private String requestMessage;
// 也可以发送二进制文件
//byte[] bytes;
}
Server发送到Client响应数据
/**
* 功能描述:Server发送到Client响应数据
*
* @author Songxianyang
* @date 2024-01-28 16:02
*/
@Data
public class RespData implements Serializable {
private String id;
private String name;
private String requestMessage;
}
Server
/**
* 功能描述:
*
* @author Songxianyang
* @date 2024-01-28 16:09
*/
public class Server {
public static void main(String[] args) throws Exception {
EventLoopGroup bossEvent = new NioEventLoopGroup(1);
EventLoopGroup workerEvent = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossEvent, workerEvent)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,128) // 设置线程队列
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingDecoder());
socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingEncoder());
socketChannel.pipeline().addLast(new ServerHandler()); // 自定义的server处理器
}
});
// 与Client 建立连接
ChannelFuture sync = serverBootstrap.bind(9999).sync();
sync.channel().closeFuture().sync();
bossEvent.shutdownGracefully(); // 关闭
workerEvent.shutdownGracefully();
}
}
ServerHandler
/**
* 功能描述:
*
* @author Songxianyang
* @date 2024-01-28 16:18
*/
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 接受客户端信息
ReqData reqData= (ReqData)msg;
System.out.println("接收到客户端消息id"+reqData.getId());
System.out.println("接收到客户端消息Name"+reqData.getName());
System.out.println("接收到客户端消息RequestMessage"+reqData.getRequestMessage());
// 响应客户端 我接受到了消息
RespData data = new RespData();
data.setId(reqData.getId());
data.setName(reqData.getName());
data.setRequestMessage("我接受到了消息");
ctx.writeAndFlush(data);
}
// 发生异常,则关闭通道
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}