学习了netty后,按照例子,编写了入门案例,深入了解netty的执行过程,记录下笔记。
服务端:
自定义服务器端业务处理类
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
* 读取数据事件
* @param ctx
* @param msg
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println("Server: " + ctx);
ByteBuf buf = (ByteBuf) msg;
System.out.println("客户端发来的消息: " + buf.toString(CharsetUtil.UTF_8));
* 数据读取完毕事件
* @param ctx
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("就是没钱", CharsetUtil.UTF_8));
* 异常发生事件
* @param ctx
* @param cause
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("通道激活触发方法");
super.channelActive(ctx);
}
启动类:
编写了一个服务器端程序,配置了线程组,配置了自定义业务处理类,并绑定端口号进行了启动
public class NettyServer {
public static void main(String[] args) throws Exception {
//1.创建一个线程组:用来处理网络事件(接受客户端连接)
EventLoopGroup bossGroup = new NioEventLoopGroup();
//2.创建一个线程组:用来处理网络事件(处理通道IO 操作)
EventLoopGroup workerGroup = new NioEventLoopGroup();
//3.创建服务器端启动助手来配置参数
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup) //4.设置两个线程组EventLoopGroup
.channel(NioServerSocketChannel.class) //5.使用NioServerSocketChannel 作为服务器端通道实现
.option(ChannelOption.SO_BACKLOG, 128) //6.设置线程队列中等待连接的个数
.childOption(ChannelOption.SO_KEEPALIVE, true) //7.保持活动连接状态
.childHandler(new ChannelInitializer<SocketChannel>() { //8.创建一个通道初始化对象
public void initChannel(SocketChannel sc) { //9.往Pipeline 链中添加自定义的业务处理handler
sc.pipeline().addLast(new NettyServerHandler()); //服务器端业务处理类
System.out.println(".......Server is ready.......");
//10.启动服务器端并绑定端口,等待接受客户端连接(非阻塞)
ChannelFuture cf = b.bind(9999).sync();
System.out.println("......Server is Starting......");
//11.关闭通道,关闭线程池
cf.channel().closeFuture().sync();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
客户端:
自定义了一个客户端业务处理类,继承ChannelInboundHandlerAdapter ,并分别重写了四个方法。
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
* 客户端连接成功 通道就绪事件
* @param ctx
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("通道就绪事件");
System.out.println("Client: " + ctx);
ctx.writeAndFlush(Unpooled.copiedBuffer("老板,还钱吧", CharsetUtil.UTF_8));
* 通道读取数据事件
* @param ctx
* @param msg
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println("通道读取数据事件");
ByteBuf in = (ByteBuf) msg;
System.out.println("服务器端发来的消息: " + in.toString(CharsetUtil.UTF_8));
* 数据读取完毕事件
* @param ctx
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
System.out.println("数据读取完毕事件");
ctx.flush();
* @param ctx
* @param cause
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
System.out.println("异常发生事件");
ctx.close();
* channel注册事件
* @param ctx
* @throws Exception
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channel注册事件");
super.channelRegistered(ctx);
* channel取消注册事件
* @param ctx
* @throws Exception
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
super.channelUnregistered(ctx);
}
启动类
public class NettyClient {
public static void main(String[] args) throws Exception {
//1.创建一个EventLoopGroup 线程组
EventLoopGroup group = new NioEventLoopGroup();
//2.创建客户端启动助手
Bootstrap b = new Bootstrap();
b.group(group) //3.设置EventLoopGroup 线程组
.channel(NioSocketChannel.class) //4.使用NioSocketChannel 作为客户端通道实现
.handler(new ChannelInitializer<SocketChannel>() { //5.创建一个通道初始化对象
@Override
protected void initChannel(SocketChannel sc) { //6.往Pipeline 链中添加自定义的业务处理handler
sc.pipeline().addLast(new NettyClientHandler()); //客户端业务处理类
System.out.println("......Client is ready.......");
//7.启动客户端,等待连接上服务器端(非阻塞)
ChannelFuture cf = b.connect("127.0.0.1", 9999).sync();
//8.等待连接关闭(非阻塞)
cf.channel().closeFuture().sync();
}