关于netty:netty-in-action学习笔记第二章-编写你的第一个netty程序

37次阅读

共计 3929 个字符,预计需要花费 10 分钟才能阅读完成。

【netty in action】学习笔记 - 第二章 编写你的第一个 netty 程序

这一章简略粗犷,整个章节都是讲一个例子,例子很简略,然而麻雀虽小五脏俱全。通过这个示例你会对编写基于 netty 的应用程序有个直观的意识。

我先上代码,前面再剖析。

先看看服务端的示例,

public class EchoServer {
    public int port;

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

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

            ChannelFuture f = b.bind().sync();
            System.out.println(EchoServer.class.getName() + "started and listen on" + f.channel().localAddress());
            f.channel().closeFuture().sync();}catch (Exception e) { }finally {group.shutdownGracefully();
        }
    }

    public static void main(String[] args) {new EchoServer(8888).start();}
}
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("netty rocks", CharsetUtil.UTF_8));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf msg) throws Exception {ByteBuf recieveMsg=(ByteBuf) msg;
        String result = ByteBufUtil.hexDump(recieveMsg).toUpperCase();// 将 bytebuf 中的可读字节 转换成 16 进制数字符串
        String result2 = ByteBufUtil.hexDump(msg.readBytes(msg.readableBytes()));
        // 看下两种形式输入的后果有什么区别
        System.out.println("client received:" + result);
        System.out.println("client received:" + result2);

    }

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

而后是客户端的示例,

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 InterruptedException {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
                        protected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());
                        }
                    });

            ChannelFuture f = b.connect().sync();
            f.channel().closeFuture().sync();}catch (Exception e) { }finally {group.shutdownGracefully().sync();}
    }

    public static void main(String[] args) {
        String host = "127.0.0.1";
        int port = 8888;

        new EchoClient(host, port).start();}
}
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.write(Unpooled.copiedBuffer("netty rocks", CharsetUtil.UTF_8));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf msg) throws Exception {ByteBuf recieveMsg=(ByteBuf) msg;
        String result = ByteBufUtil.hexDump(recieveMsg).toUpperCase();// 将 bytebuf 中的可读字节 转换成 16 进制数字符串
        String result2 = ByteBufUtil.hexDump(msg.readBytes(msg.readableBytes()));
        // 看下两种形式输入的后果有什么区别
        System.out.println("client received:" + result);
        System.out.println("client received:" + result2);

    }

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

这个代码是能够运行的。你能够本人跑一下。

上面就来解释下下面这些代码。当然这里只做简略的解释,因为每个概念在前面的章节都有具体的形容。

Bootstrap用来启动服务,客户端和服务端都应用这个。区别在于服务端应用的是 ServerBootstrap。这两个类都是继承自AbstractBootstrap 这个抽象类。

NioEventLoopGroup用来解决多个连贯,能够把它了解为线程池。

NioServerSocketChannel当然就是 netty 里最外围的概念 channel。这里咱们指定 channel 的类型。当然这里你能够指定OioServerSocketChannel,示意阻塞的 IO channel。

咱们通过 childHandler 指定业务解决外围逻辑的 handler,这些 handler 是以链的形式治理的。ChannelPipeline是这个链的名字。这其实也是设计模式中的责任链模式。

接着咱们通过 bind 办法绑定服务器,sync示意这是一个阻塞的同步调用,在绑定胜利之前都会期待。

EchoServerHandlerEchoClientHandler 是咱们业务解决类,他们的设计办法就是咱们后面章节说到的回调。看房办法的名字也能猜出一二。咱们须要继承 ChannelInboundHandlerAdapter 表明这是一个入口处的解决类。(进口和入口的前面会具体阐明)。

channelRead办法在服务端(客户端)收到数据时被调用,exceptionCaught是异样产生时调用。

须要留神的是,在接收数据的时候,channelRead(channelRead0)可能会调用屡次,比方接管 5 个字节,第一次收到 3 个,第二次收到 2 个。这其实是 netty 外面拆包,粘包的概念,这个在前面的章节也会讲到,这里不多说。只管会呈现拆包,粘包的状况,然而 netty 能保障在 TCP 协定下,数据接管的程序和发送的程序是统一的。(这个也是 netty 很多自带的解码器解决粘包的前提)

正文完
 0