美文网首页
netty的使用和相关知识

netty的使用和相关知识

作者: 无聊之园 | 来源:发表于2019-05-12 11:37 被阅读0次

1.不直接使用nio的理由:

直接使用nio你需要额外处理很多问题:网络闪断、客户端重复接入、客户端安全认证、消息的编解码、半包读写等。
nio使用复杂,还有小bug。

2.netty的简单例子:

netty使用比较简单,不同的场景对一个不同的hadler。

public class MyServer {

    public static void main(String[] args) {
        // EventLoopGroup包含了一组线程,bosstrap用于多线程接受客户端accept连接
        EventLoopGroup  bossstrap = new NioEventLoopGroup();
      // workstrap用于多线程处理连接后的channel读写 
       EventLoopGroup  workerstrap = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
         // 绑定线程组,之后,设置创建的channel为nioserverSocketChannel了,//之后绑定日志处理handler,之后绑定自定义serverInitializer,handler使用bosstrap线程组,childhandler使用workerstrap线程组
        serverBootstrap.group(bossstrap, workerstrap)
                .channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new MyServerInitializer());
        try {
               // 绑定端口,异步返回
            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            // channelFuture类似于juc的Future,线程执行后的获取结果,线程没有执行完,则堵塞。channelFuture等服务端链路关闭之后回调。
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossstrap.shutdownGracefully();
            workerstrap.shutdownGracefully();
        }


    }
}
// 绑定的channel初始化器
public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        // 责任链模式,添加解码器。
        // LengthFieldBasedFrameDecoder是对固定长度消息头步(记录了消息体长度),消息体的这种数据进行解码,防止粘包拆包。
        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
        // 把消息进行消息头、消息体的形式进行打包
        pipeline.addLast(new LengthFieldPrepender(4));
       // byte转strig的解码器
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
        // 自定义处理器
        pipeline.addLast(new MyServerHandle());
    }
}
public class MyServerHandle extends SimpleChannelInboundHandler<String> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println(ctx.channel().remoteAddress() + ", " + msg);
        ctx.channel().writeAndFlush("from server:" + UUID.randomUUID());
    }

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

客户端

public class MyClient {

    public static void main(String[] args) {
        // 客户端只有一个连接通道,所以只需要一个处理通道的读写线程池就可以
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            // 对应服务端的ServerBootstrap
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                    .handler(new MyClientInitalizer());
            ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            eventLoopGroup.shutdownGracefully();
        }

    }
}
public class MyClientInitalizer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
        pipeline.addLast(new LengthFieldPrepender(4));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));

        pipeline.addLast(new MyClientHandle());
    }
}
public class MyClientHandle extends SimpleChannelInboundHandler<String> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println(ctx.channel().remoteAddress());
        System.out.println("client output:" + msg);
        ctx.writeAndFlush("from client: " + LocalDateTime.now());
    }

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

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush("来自客户端的问候");
    }
}

3. netty相关的问题

netty有很多种编码节码,组成了netty的丰富的功能,比如netty做http服务器,netty做websocket,都有对应的编码器封装。

1.粘包拆包:

tcp流,和发送的多条数据,有可能会粘在一起,或者只发送了一半。

解决思路:1.消息定长。2.加分隔符,比如回车符。3.消息头,消息体,消息头包含消息长度。4.更复杂的应用协议。

netty对粘包拆包提供很多解码器:LineBasedFrameDecoder,利用分隔符来处理粘包拆包。还有上面例子的LengthFieldBasedFrameDecoder,利用消息头消息体的形式。

2.系列化

java自带的系列化机制的缺点。

1.无法跨语言。
2.系列化后的字节数太大。
3.系列化性能低。

xml和json:
系列化后字节数大,性能低。

其他的系列化框架
google protobuf:跨多种语言,性能高,结构化数据。

使用步骤:编写prot文件,使用prot编译器,编译文件,生成java文件,用生成java类对对象进行编码节码。

thift:跟protobuf类似,比protobuf功能更丰富。

netty对各种系列化都有对应的编码解码类,直接使用就可以。

3. 零拷贝

其实就是,直接开辟堆外内存,省去了java堆到内核的一层拷贝。

相关文章

  • netty的使用和相关知识

    1.不直接使用nio的理由: 直接使用nio你需要额外处理很多问题:网络闪断、客户端重复接入、客户端安全认证、消息...

  • Java I/O回顾

    最近在学习netty,其中有对比bio、nio、netty使用上的不同,也趁此机会回顾了相关知识,加深下理解,主要...

  • Netty源码(二):Netty的Channel和Pipelin

    本文主要讲述Netty框架中Channel相关的知识,Netty通过Channel和Pipeline等一些组件提供...

  • Netty是什么

    本文基于Netty4.1展开介绍相关理论模型,使用场景,基本组件、整体架构 Netty简介 Netty是 一个异步...

  • JAVA-每日一面 2022-01-24

    说说Netty 线程模型和 Netty 的零拷贝 Netty 线程模型首先,Netty 使用 EventLoop ...

  • 【第25篇】Netty相关的项目汇总清单

    1、Netty相关的项目 Netty相关的项目清单来自Netty官方 2、Netty国外产品系列 Akka 是一...

  • Java读源码之Netty深入剖析[百度网盘分享]

    第1章 课程介绍 介绍本课程需要的前提知识和内容概要 1-1 Netty深入剖析 第2章 Netty基本组件 使用...

  • Netty源码(一):Netty中的Buffer

    最近我学习了NIO相关的知识,然后发现了Netty这个基于NIO的网络应用框架,于是就研究起Netty框架源码,来...

  • rocket源码 start

    netty在rocket中的使用 client和server都是使用netty通信 client在创建BootSt...

  • Futuer研究

    Future是什么? 最近写了一些关于netty的相关代码,发现类似netty 的这种异步框架大量的使用一个Fut...

网友评论

      本文标题:netty的使用和相关知识

      本文链接:https://www.haomeiwen.com/subject/bhnqaqtx.html