Netty入门

Netty入门目录

  • Netty开发环境
  • 服务端程序Demo
  • 客户端程序Demo
  • 运行结果

Netty环境搭建

搭建maven项目引入相关jar,目前最新的jar为netty-all-5.0.0.Alpha2.jar。

<dependency>
	<groupId>io.netty</groupId>
	<artifactId>netty-all</artifactId>
	<version>5.0.0.Alpha2</version>
</dependency>

Netty服务端Demo

废话不多少,直接上代码

package com.example.netty.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @version 1.0
 * @Desription:
 * @Author:Hui
 * @CreateDate:2018/6/16 21:03
 */
public class TimeServer {
    public static void main(String[] args) {
        int port = 8080;
        if(args != null && args.length > 0){
            port = Integer.valueOf(args[0]);
        }
        try {
            new TimeServer().bind(port);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public  void bind(int port) throws Exception {
        //配置服务端NIO线程组,这里创建了2个NioEventLoopGrou,
        // 专门用于网络事件处理。一个用于服务端接受客户端连接,一个进行SocketChannel的网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //new ServerBootsrap()是Netty用于启动NIO服务端的辅助启动类。
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup,workerGroup)
                    //此处相当于设置创建Channel为NIOServerSocketChannel,它的功能对应JDK NIO中的ServerSocketChannel。
                    .channel(NioServerSocketChannel.class)
                    //
                    .option(ChannelOption.SO_BACKLOG,1024)
                    // 绑定I/O事件的处理类,它的作用是用于网络I/O读写
                    .childHandler(new ChildChannelHandler());
            //绑定监听端口,随后调用它的同步阻塞方法sync等待绑定操作完成。成功后返回一个ChannelFuture,主要用于异步操作的通知回调
            ChannelFuture future = b.bind(port).sync();
            //此处进行方法阻塞,等待服务端链路关闭后,main函数才推出
            future.channel().closeFuture().sync();
        } finally {
            // shutdownGracefully()方法释放跟shutdownGracefull相关联的资源。优雅退出
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            socketChannel.pipeline().addLast(new TimeServerHandler());
        }
    }
}

package com.example.netty.server;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

import java.util.Date;

/**
 * @version 1.0
 * @Desription: 继承ChannelHandlerAdpater,用于网络事件进行读写操作,通常我们只需要关注channelRead和exceptionCaught方法
 * @Author:Hui
 * @CreateDate:2018/6/16 21:11
 */
public class TimeServerHandler extends ChannelHandlerAdapter {
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //当发生异常时,关闭ChannelHandlerContext,释放和ChannelHandlerContext相关的句柄等资源

        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //类型转换为Netty的ByteBuf对象,相当于NIO的ByteBuffer。
        ByteBuf buf = (ByteBuf) msg;
        //buf.readableBytes()方法获取了缓冲区可读的字节数,可根据字节数创建byte数组
        byte[] req = new byte[buf.readableBytes()];
        //readBytes方法将缓冲区的字节数复制到新建的数组中
        buf.readBytes(req);
        String body = new String(req,"UTF-8");
        System.out.println("The Time Server receive order : " + body );
        String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
        ctx.write(resp);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //此方法将消息返送到SocketChannel中发送给对方。
        ctx.flush();
    }
}

Netty客户端Demo

package com.example.netty.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * @version 1.0
 * @Desription:
 * @Author:Hui
 * @CreateDate:2018/6/16 21:22
 */
public class TimeClient01 {
    public static void main(String[] args) {
        int port = 8080;
        if(args != null && args.length > 0 ){
            port = Integer.valueOf(args[0]);
        }
        try {
            new TimeClient01().connect(port,"127.0.0.1");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void connect(int port, String host) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new TimeClientHandler());
                        }
                    });
            ChannelFuture f = b.connect(host,port).sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

package com.example.netty.client;

import com.example.nio.client.TimeClientHandle;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandlerInvoker;
import io.netty.util.concurrent.EventExecutorGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @version 1.0
 * @Desription:
 * @Author:Hui
 * @CreateDate:2018/6/16 21:28
 */
public class TimeClientHandler extends ChannelHandlerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(TimeClientHandle.class);

    private final ByteBuf firstMessage;

    public TimeClientHandler() {
        byte[] req = "QUERY TIME ORDER".getBytes();
        firstMessage = Unpooled.buffer(req.length);
        firstMessage.writeBytes(req);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.warn("Unexpected exception from downstream : " + cause.getMessage());
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(firstMessage);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        String body = new String(req,"UTF-8");
        System.out.println("Now is "+ body);
//        ctx.close();
    }
}

运行调试

服务端结果:

23:04:58.777 [main] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
23:04:58.777 [main] DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 8
23:04:58.808 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
23:04:58.808 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
23:04:58.980 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 98:ee:cb:67:ea:36:00:00 (auto-detected)
23:04:58.996 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.processId: 1124 (auto-detected)
23:04:58.996 [main] DEBUG io.netty.util.internal.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0xc4537a7c14e729e1
23:04:59.011 [main] DEBUG io.netty.channel.ChannelOutboundBuffer - -Dio.netty.threadLocalDirectBufferSize: 65536
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - Platform: Windows
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - Java version: 8
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noUnsafe: false
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.ByteBuffer.cleaner: available
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: true
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noJavassist: false
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - Javassist: unavailable
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - You don't have Javassist in your class path or you don't have enough permission to load dynamically generated classes.  Please check the configuration for better performance.
23:04:59.027 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
23:04:59.058 [main] DEBUG io.netty.util.NetUtil - Loopback interface: Software Loopback Interface 1
23:04:59.058 [main] DEBUG io.netty.util.NetUtil - Loopback address: /127.0.0.1 (primary)
23:04:59.058 [main] DEBUG io.netty.util.NetUtil - Loopback address: /0:0:0:0:0:0:0:1

客户端结果:

23:07:04.308 [main] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
23:07:04.308 [main] DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 8
23:07:04.340 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
23:07:04.340 [main] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
23:07:04.511 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 98:ee:cb:67:ea:36:00:00 (auto-detected)
23:07:04.527 [main] DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.processId: 3736 (auto-detected)
23:07:04.527 [main] DEBUG io.netty.util.internal.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0xbaf957b74d4b8d21
23:07:04.543 [main] DEBUG io.netty.channel.ChannelOutboundBuffer - -Dio.netty.threadLocalDirectBufferSize: 65536
23:07:04.558 [main] DEBUG io.netty.util.internal.PlatformDependent - Platform: Windows
23:07:04.558 [main] DEBUG io.netty.util.internal.PlatformDependent - Java version: 8
23:07:04.558 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noUnsafe: false
23:07:04.558 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.ByteBuffer.cleaner: available
23:07:04.558 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: true
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noJavassist: false
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent - Javassist: unavailable
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent - You don't have Javassist in your class path or you don't have enough permission to load dynamically generated classes.  Please check the configuration for better performance.
23:07:04.574 [main] DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
23:07:04.590 [nioEventLoopGroup-2-1] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetectionLevel: simple
Now is Sat Jun 16 23:07:04 CST 2018

此时服务端新增日志:

23:07:04.605 [nioEventLoopGroup-3-1] DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetectionLevel: simple
The Time Server receive order : QUERY TIME ORDER

运行结果正确。**注意:**此时client不会主动关闭,只要链路不断,client就不关闭。

总结

这里对Netty代码作了一个简单的了解,如果有兴趣,可跟下来深入解读。

转载于:https://my.oschina.net/mrku/blog/1831396

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值