本文介绍了简单的Netty服务端和客户端的代码示例。简单描述了一下InboundHandler和OutboundHandler的关系。
NettyServer服务端代码模板
/**
* netty服务端代码
*/
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(5);
try {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(bossGroup,workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,512)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//解码器
pipeline.addLast(new StringDecoder());
//编码器
pipeline.addLast(new StringEncoder());
//自定义处理的handler
pipeline.addLast(new NettyServerHandler());
}
});
ChannelFuture cf = bootstrap.bind(9000).sync();
//给cf注册监听器
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (cf.isSuccess()){
//连接成功事件
}else {
//连接失败事件
}
}
});
//对通道关闭进行监听,closeFuture是异步操作。监听通道关闭。。.sync()是同步等待通道关闭
cf.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
NettyServer自定义handler
/**
* 只重写了基础常用的功能
*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
/**
* channel连接事件
* @param ctx
*/
@Override
public void channelActive(ChannelHandlerContext ctx){
Channel channel = ctx.channel();
ctx.writeAndFlush(channel.remoteAddress()+",已经连接");
}
/**
* 读取客户端发送的数据
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println("服务读取线程:"+Thread.currentThread().getName());
// ByteBuf buf = (ByteBuf)msg;
System.out.println("接收客户端消息:"+msg.toString());
}
/**
* 读取完毕的处理方法
* @param ctx
* @throws Exception
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ByteBuf buf = Unpooled.copiedBuffer("helloClient",StandardCharsets.UTF_8);
ctx.writeAndFlush(buf);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause){
ctx.close();
}
}
NettyClient代码模板
/**
* 客户端代码
*/
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//解码器
pipeline.addLast(new StringDecoder());
//编码器
pipeline.addLast(new StringEncoder());
pipeline.addLast(new NettyClientHandler());
}
});
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",9000).sync();
channelFuture.channel().closeFuture().sync();
}finally {
group.shutdownGracefully();
}
}
}
NettyClientHandler代码示例
/**
* 只重写了基础常用的功能
*/
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
/**
* 客户端连接服务端完成时,会触发这个方法
*
* @param ctx
*/
@Override
public void channelActive(ChannelHandlerContext ctx) {
ByteBuf buf = Unpooled.copiedBuffer("helloServer", Charsets.UTF_8);
ctx.writeAndFlush(buf);
}
/**
* 当通道有读取事件时,会触发。服务端发送数据给客户端时
*
* @param ctx
* @param msg
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// ByteBuf buf = (ByteBuf)msg;
System.out.println("收到服务端消息:"+msg.toString());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
Handler有两种类型:InboundHandler和OutboundHandler
InboundHandler是输入的数据流向,是从上向下的。
OutboundHandler的输出的数据流量,是从下向上的。
当然,这个输入和输出都是相对来说的。
我们写netty程序也是遵循netty给我们固定的流程,来开发对应的数据处理handler。
本篇文章简单介绍了netty的服务端和客户端的基本写法。后面会补充拆包粘包的处理。