Netty简单使用

一、环境准备

需要提前将需要的jar包导入到项目中:

netty-all-4.1.25.Final.jar

 

二、简单说明

1. 使用Netty框架来编写服务器代码是为了实现Java的NIO编程

 

三、服务器端

服务器端分为两部分:调度部分业务逻辑部分

 

调度部分:

1. 创建调度工具对象:

ServerBootstrap serverBootstrap = new ServerBootstrap();

2. 创建线程池组:

NioEventLoopGroup group = new NioEventLoopGroup();

3. 调度:

serverBootstrap.localAddress(host, port)
                .group(group)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        channel.pipeline().addLast(new ServerHandler1());
                        channel.pipeline().addLast(new ServerHandler3());
                        channel.pipeline().addLast(new ServerHandler4());
                        channel.pipeline().addLast(new ServerHandler2());
                    }
                });

说明:

ServerHandler1,ServerHandler2...是业务逻辑的类,通过channel来调用

这里业务逻辑类必须是继承自ChannelInboundHandler或者ChannelOutboundHandler,或者他们的子类

上述例子中:

ServerHandler1和ServerHandler2都是属于ChannelInboundHandler的子类

ServerHandler3和ServerHandler4都是属于ChannelOutboundHandler的子类

这里有一个规定:最后一个添加的业务逻辑必须是inbound,否则如果最后一个是outbound的话,将不会被执行到。

执行顺序:先执行inbound再执行outbound,inbound按照添加的顺序执行,outbound按照添加的相反顺序执行。

如上述例子中执行顺序为ServerHandler1,ServerHandler2,ServerHandler4,ServerHandler3

3. 绑定服务器:

ChannelFuture channelFuture = serverBootstrap.bind().sync();

4. 关闭channel:

channelFuture.channel().closeFuture().sync();

5. 关闭线程组:

group.shutdownGracefully();

 

业务逻辑部分:

这里分开来谈

inbound部分:

1. 需要继承自ChannelInboundHandler或者他的子类下

2. 重写方法并在方法中补全相应的业务逻辑:channelRead(ChannelHandlerContext ctx, Object msg)

3. 如果后面还有inbound的流水线,则在后面调用方法:ctx.fireChannelRead(msg);

4. 如果后面就是outbound的流水线了,则在后面调用方法:ctx.write(msg);

 

outbound部分:

1. 需要继承自ChannelOutboundHandler或者他的子类下

2. 重写方法并在方法中补全相应的业务逻辑:write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)

3. 如果后面还有inbound的流水线,则在后面调用方法:ctx.fireChannelRead(msg);

4. 如果后面就是outbound的流水线了,则在后面调用方法:ctx.write(msg);

 

四、客户端

客户端也分为两部分:调度部分业务逻辑部分

 

调度部分:

1. 创建调度工具对象:

Bootstrap bootstrap = new Bootstrap();

2. 创建线程池组:

NioEventLoopGroup group = new NioEventLoopGroup();

3. 调度:

bootstrap.remoteAddress(host, port)
                .group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        channel.pipeline().addLast(new ClientHandler2());
                        channel.pipeline().addLast(new ClientHandler1());
                    }
                });

4. 连接服务器:

ChannelFuture channelFuture = bootstrap.connect().sync();

5. 关闭channel:

channelFuture.channel().closeFuture().sync();

6. 关闭线程组:

group.shutdownGracefully();

 

业务逻辑部分:

同前面服务器端设计相同。

 

五、发送消息的具体实现

通过ChannelHandlerContext对象发送消息,需要将消息封装成ByteBuf

1. 将发送内容确定好:

String content = "hello server, m client";

2. 将内容转成字节数组:

byte[] bytes = content.getBytes();

3. 创建ByteBuf对象:

ByteBuf byteBuf = Unpooled.buffer(bytes.length);

4. 将字节数组中的内容写入ByteBuf

byteBuf.writeBytes(bytes);

5. 发送消息

ctx.writeAndFlush(byteBuf);

 

接收消息和发送消息相反,一般会直接拿到一个ByteBuf对象,需要将其反转成字符串

1. 创建字节数组

byte[] bytes = new byte[byteBuf.readableBytes()];

2. 将内容写入字节数组

byteBuf.readBytes(bytes);

3. 转成字符串

new String(bytes,"UTF-8")
posted @ 2018-05-27 01:18  shuxte  阅读(800)  评论(0编辑  收藏  举报