Netty4详解二:开发第一个Netty应用程序

package NettyDemo.echo.handler;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.channel.ChannelHandler.Sharable;/** * Sharable表示此对象在channel间共享 * handler类是我们的具体业务类 * */@Sharable//注解@Sharable可以让它在channels间共享public class EchoServerHandler extends ChannelInboundHandlerAdapter{public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("server received data :" + msg); ctx.write(msg);//写回数据,} public void channelReadComplete(ChannelHandlerContext ctx) { ctx.writeAndFlush(Unpooled.EMPTY_BUFFER) //flush掉所有写回的数据.addListener(ChannelFutureListener.CLOSE); //当flush完成后关闭channel} public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) { cause.printStackTrace();//捕捉异常信息ctx.close();//出现异常时关闭channel } }

2.3.3关于异常处理:

我们在上面程序中也重写了exceptionCaught方法,这里就是对当异常出现时的处理。

2.4 写一个Netty Client

一般一个简单的Client会扮演如下角色:

4.4.1BootsTrapping的过程:

和Server端类似,只不过Client端要同时指定连接主机的IP和Port。

package NettyDemo.echo.client;import io.netty.bootstrap.Bootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import java.net.InetSocketAddress;import NettyDemo.echo.handler.EchoClientHandler;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);b.channel(NioSocketChannel.class);b.remoteAddress(new InetSocketAddress(host, port));b.handler(new ChannelInitializer<SocketChannel>() {public void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());}});ChannelFuture f = b.connect().sync();f.addListener(new ChannelFutureListener() {public void operationComplete(ChannelFuture future) throws Exception {if(future.isSuccess()){System.out.println("client connected");}else{System.out.println("server attemp failed");future.cause().printStackTrace();}}});f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws Exception {new EchoClient("127.0.0.1", 3331).start();}} 1. 创建一个ServerBootstrap实例 2. 创建一个EventLoopGroup来处理各种事件,如处理链接请求,发送接收数据等。 3. 定义一个远程InetSocketAddress好让客户端连接 4. 当连接完成之后,Handler会被执行一次 5. 所有准备好之后调用ServerBootstrap.connect()方法连接Server

4.4.2 业务逻辑ClientHandler:

我们同样继承一个SimpleChannelInboundHandler来实现我们的Client,我们需要重写其中的三个方法:

package NettyDemo.echo.handler;import io.netty.buffer.ByteBuf;import io.netty.buffer.ByteBufUtil;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.channel.ChannelHandler.Sharable;import io.netty.util.CharsetUtil;@Sharablepublic class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {/** *此方法会在连接到服务器后被调用 * */public void channelActive(ChannelHandlerContext ctx) {ctx.write(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));}/** *此方法会在接收到服务器数据后调用 * */public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) {System.out.println("Client received: " + ByteBufUtil.hexDump(in.readBytes(in.readableBytes())));}/** *捕捉到异常 * */public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}} 其中需要注意的是channelRead0()方法,此方法接收到的可能是一些数据片段,,比如服务器发送了5个字节数据,Client端不能保证一次全部收到,比如第一次收到3个字节,第二次收到2个字节。我们可能还会关心收到这些片段的顺序是否可发送顺序一致,这要看具体是什么协议,比如基于TCP协议的字节流是能保证顺序的。

还有一点,在Client端我们的业务Handler继承的是SimpleChannelInboundHandler,而在服务器端继承的是ChannelInboundHandlerAdapter,那么这两个有什么区别呢?最主要的区别就是SimpleChannelInboundHandler在接收到数据后会自动release掉数据占用的Bytebuffer资源(自动调用Bytebuffer.release())。而为何服务器端不能用呢,因为我们想让服务器把客户端请求的数据发送回去,而服务器端有可能在channelRead方法返回前还没有写完数据,因此不能让它自动release。

人生就是要感受美丽的善良的,丑恶的病态的。

Netty4详解二:开发第一个Netty应用程序

相关文章:

你感兴趣的文章:

标签云: