netty的入门示例

发表时间:2017-09-12 17:00:08 浏览量( 29 ) 留言数( 0 )

学习目标:

1、Netty的入门示例

2、对Netty有初步的认识


学习过程:

一、netty的入门示例

先引入netty的依赖

修改pom.xml文件

		<dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
			<version>4.1.15.Final</version>
		</dependency>

下面我们看一下Netty的一个监听的通讯示例,大家对代码初步有一个认识即可,以后我们在慢慢介绍

(1)服务类

public class EchoServer {
    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }


    public void start() throws Exception {
        final EchoServerHandler serverHandler = new EchoServerHandler();
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(group)
                .channel(NioServerSocketChannel.class)
                .localAddress(new InetSocketAddress(port))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(serverHandler);
                    }
                });

            ChannelFuture f = b.bind().sync();
            System.out.println(EchoServer.class.getName() +
                " 启动了,并开始监听: " + f.channel().localAddress());
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }
    

    public static void main(String[] args)
        throws Exception {
        int port = 1000;
        new EchoServer(port).start();
    }
    
}

(2)服务端业务处理类

@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
	
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
    	System.out.println("Netty Server 建立连接了。!");
        ctx.writeAndFlush(Unpooled.copiedBuffer("欢迎客户端!",
                CharsetUtil.UTF_8));
    }
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		ByteBuf in = (ByteBuf) msg;
		System.out.println("Server 收到消息: " + in.toString(CharsetUtil.UTF_8));

		String hello = "你好";
        //返回消息给客户端
		ctx.write(Unpooled.copiedBuffer(hello, CharsetUtil.UTF_8));
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		System.out.println("channelReadComplete");
		ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		System.out.println("exceptionCaught");
		cause.printStackTrace();
		ctx.close();
	}
}

服务器端代码说明:

    1.NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器,Netty 提供了许多不同的 EventLoopGroup 的实现用来处理不同的传输。在这个例子中我们实现了一个服务端的应用,我们只是使用了一个NioEventLoopGroup,一般来说会有2个 NioEventLoopGroup 会被使用。第一个经常被叫做‘boss’,用来接收进来的连接。第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上。如何知道多少个线程已经被使用,如何映射到已经创建的 Channel上都需要依赖于 EventLoopGroup 的实现,并且可以通过构造函数来配置他们的关系。再下一节课我们会详细讲一下这个内容。

    2.ServerBootstrap 是一个启动 NIO 服务的辅助启动类。你可以在这个服务中直接使用 Channel,但是这会是一个复杂的处理过程,在很多情况下你并不需要这样做。

    3.这里我们指定使用 NioServerSocketChannel 类来举例说明一个新的 Channel 如何接收进来的连接。

    4.这里的事件处理类经常会被用来处理一个最近的已经接收的 Channel。ChannelInitializer 是一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel。也许你想通过增加一些处理类比如我们这里就自定以了一个Channel, 通过一个新的 Channel 或者其对应的ChannelPipeline 来实现你的网络程序。当你的程序变的复杂时,可能你会增加更多的处理类到 pipline 上,然后提取这些匿名类到最顶层的类上,这些channel会想拦截器一样逐个执行,当然你也可以根据自己的需要停止它。

    5.我们继续,剩下的就是绑定端口然后启动服务。这里我们在机器上绑定了机器的 端口。当然现在你可以多次调用 bind() 方法(基于不同绑定地址)。

    Netty的这段代码对初学者来说比较长,当时基本也就是这样的一个模板。我们只需要做好笔记就行了。更多的时需要编写Channel的Handler进行业务处理就行了。

(3)客户端类

public class EchoClient {
	private final String host;
	private final int port;

	public EchoClient(String host, int port) {
		this.host = host;
		this.port = port;
	}


	public void start() throws Exception {
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port))
					.handler(new ChannelInitializer<SocketChannel>() {
						@Override
						public void initChannel(SocketChannel ch) throws Exception {
							ch.pipeline().addLast(new EchoClientHandler());
						}
					});
			ChannelFuture f = b.connect().sync();
			f.channel().closeFuture().sync();
		} finally {
			group.shutdownGracefully().sync();
		}
	}
	

	public static void main(String[] args) throws Exception {

		final String host = "localhost";
		final int port = 1000;
		new EchoClient(host, port).start();
	}

}

(4)客户端业务处理类

@Sharable
public class EchoClientHandler
    extends SimpleChannelInboundHandler<ByteBuf> {
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
    	System.out.println("Netty Client 建立连接了。!");
        ctx.writeAndFlush(Unpooled.copiedBuffer("我是客户端。",
                CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) {
        System.out.println(
                "Client 收到: " + in.toString(CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
        Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}


二、netty切换不同IO

    可以看到Netty的代码非常简介,如果我们需要切换到BIO,那么只需要修改其中的几个参数和变量即可。非常简单。