【netty笔录】-“hello world”

                     **用netty写个hello world**				

要成为架构师,了解一些框架内部的通信机制的必不可少的,所以最近学习了netty的相关知识,本次就先用netty写个“hello world”来体验下。
Netty或多或少应该都听说过,我这里就不用在赘述他的背景,netty的内部通讯模式有多种:
NIO io.netty.channel.socket.nio 使用java.nio.channels 包作为基础——基于选择器的方式
Epoll io.netty.channel.epoll 由 JNI 驱动的 epoll()和非阻塞 IO。这个传输支持只有在Linux 上可用的多种特性,按照作者的话来说在linux下使用这种通讯模式能获得更高的性能,能减少GC次数.将NioEventLoopGroup替换为EpollEventLoopGroup , 并且将NioServerSocketChannel.class 替换为EpollServerSocketChannel.class 即可。
OIO io.netty.channel.socket.oio 使用java.net 包作为基础——使用阻塞流(相当于BIO)
Local io.netty.channel.local 可以在VM 内部通过管道进行通信的本地传输
Embedded io.netty.channel.embedded Embedded 传输,允许使用ChannelHandler 而又不需要一个真正的基于网络的传输。在测试ChannelHandler 实现时非常有用

这里主要是用NIO的方式,NIO的原理会单独分享和实现,netty的帮助程序员封装起了NIO的使得代码编写起来会比较简单,了解一个新的东西要先从大的方向去了解,netty的核心组件:
1.channel java的channel是网络io和文件io通用,netty的channel只包含网络通讯的功能。
netty的channel并没有继承java的channel;
2、EventLoop、EventLoopGroup
结构图
3.事件和ChannelHandler
应用程序开发人员的角度来看,Netty 的主要组件是ChannelHandler,
它充当了所有处理入站和出站数据的应用程序逻辑的地方。
Netty 以适配器类的形式提供了大量默认的ChannelHandler 实现,
帮我们简化应用程序处理逻辑的开发过程。
开始:
先写客户端:

public class NettyClient {


    private ChannelFuture f;
    public void connect(String ip,Integer port){
        EventLoopGroup  eventLoopGroup = new NioEventLoopGroup();
        //程序启动器
        Bootstrap b =new Bootstrap();

        try {
        b.group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>(){

                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new NettyClientHandler());
                    }
                });
            f = b.connect(ip, port).sync();/*连接到远程节点,阻塞等待直到连接完成*/
            f.channel().closeFuture().sync();/*阻塞,直到channel关闭*/
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }


    public static void main(String[] args) {
        int port =8080;
        NettyClient client = new NettyClient();
        client.connect("localhost",port);
    }


Netty是 Reactor模型的是基于事件驱动的,所以可以看到具体业务是由handler来处理, ChannelPipeline 提供了ChannelHandler 链的容器,并定义了用于在该链上传播入站和出站事件流的API。

public class NettyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    protected NettyClientHandler() {
        super();
    }



    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
//        System.out.println("hello , i am client");
        ByteBuf buf= Unpooled.copiedBuffer("hello server",CharsetUtil.UTF_8);
        ctx.writeAndFlush(buf);
    }

   /* @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        super.channelRead(ctx, msg);
        ByteBuf buf= (ByteBuf) msg;
        System.out.println("accept msg:" + buf.toString(CharsetUtil.UTF_8));

    }*/

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
        System.out.println("client accept:"+byteBuf.toString(CharsetUtil.UTF_8));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }

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

服务端:

 public void bind(Integer port){
        EventLoopGroup bossGroup=new NioEventLoopGroup();//selector[]
        EventLoopGroup workGroup=new NioEventLoopGroup();
        ServerBootstrap b =new ServerBootstrap();
        try {
            b.group(bossGroup,workGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>(){

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new NettyServerOutBandHandler());
                            socketChannel.pipeline().addLast(new NettyServerInBandHandler());
                        }
                    });
            ChannelFuture f =b.bind(port).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        Integer port =8080;
        NettyServer nettyServer= new NettyServer();
        nettyServer.bind(port);
    }

ChannelPipeline是有入栈出站顺序的,通常把出站的放在前面,因为有执行顺序会先执行出站的读,可以做检测过滤相关操作

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

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
        System.out.println("server accept:"+byteBuf.toString(CharsetUtil.UTF_8));
    }


    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        System.out.println("读完");
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello client 3",CharsetUtil.UTF_8));
    }

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

定义了一个出站的handler和一个入栈的

public class NettyServerOutBandHandler extends ChannelOutboundHandlerAdapter {
    public NettyServerOutBandHandler() {
        super();
    }

    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception {
        super.connect(ctx, remoteAddress, localAddress, promise);
        System.out.println("连接成功!");
    }

    @Override
    public void read(ChannelHandlerContext ctx) throws Exception {
        super.read(ctx);
//        System.out.println(ctx.read());

//        ctx.writeAndFlush(Unpooled.copiedBuffer("hello client1",CharsetUtil.UTF_8));

    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        super.write(ctx, msg, promise);
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello client2",CharsetUtil.UTF_8));

    }
}

运行结果,先启动服务端,后启动客户端

服务端输出
客户端输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值