栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java网络之Netty学习(1)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java网络之Netty学习(1)

是什么?

是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。基于Nio的

特点?
    高并发,基于Nio的传输快,使用零拷贝,减少不必要的内存拷贝封装好,简化了Nio的API高性能体现:IO线程模型,内存零拷贝,内存池设计,申请的内存可以重复使用,指直接内存,高性能序列化协议。
TCP粘包/拆包问题和解决

是什么:TCP是基于流进行传输数据,可能把数据拆成几个包。也可能把几个小的数据封装成一个大的包发送
粘包就是,小的数据合并一个大的包。
拆包就是:大的数据,超过了TCP报文最大长度,就会拆包。
解决就是:类似编码解码,拆包和粘包用同样的协议。Netty中已经有了拆包器。

    固定长度,每个数据包长度是固定的。行拆包器,发送端将每个数据包直接使用换行符分割,接收端也是将粘过来的数据按照换行符进行拆包分隔符拆包器,自定义符号行拆包器按照长度进行拆包。
    ch.pipeline().addLast(new FixedLengthframeDecoder(31));
Netty的零拷贝

传统发送数据的四次拷贝
1.数据从磁盘拷贝的内存的read buffer
2. 数据从read buffer拷贝到用户缓存区
3. 从用户缓存区拷贝到内存的Socket buffer
4. 从内核Socket buffer拷贝到网卡缓存区

零拷贝就是省略第2和第3步。
Netty中零拷贝的体现:
1.bytebuffer,使用的是堆外内存直接进行Socket读写。传统的JVM会将堆内数据拷贝一份到直接内存,然后写入Socket,多一次内存拷贝。
2.组合buffer对象,两个buffer组合在一起不是新申请一个大的buffer,而是使用组合buffer保留这两个buffer的引用。
3. 文件传输FileChannnel.transferTo,就是省略第2第3步。

Netty使用的Demo

io.netty netty-all 4.1.58.Final

    创建服务端启动类
package com.example.demo.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class Myserver {
    public static void main(String[] args) {
        //1.创建两个线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        //2.创建服务器启动对象,设置参数
        ServerBootstrap bootstrap = new ServerBootstrap();
        //设置两个线程池组
        bootstrap.group(bossGroup,workerGroup)
                //设置服务端通道实现类型
                .channel(NioServerSocketChannel.class)
                //设置线程队列得到连接个数
                .option(ChannelOption.SO_BACKLOG,128)
                //设置保持活动连接状态
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                //使用匿名内部类初始化通道对象
                .childHandler(new ChannelInitializer() {

                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast((ChannelHandler) new MyServerHandler());
                    }
                });
        System.out.println("服务端准备完毕");
        try {
            ChannelFuture channelFuture = bootstrap.bind(6666).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

    创建服务端处理器
package com.example.demo.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

public class MyServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //获取客户端发送的消息
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("收到客户端" + ctx.channel().remoteAddress() + "发送的消息:" + byteBuf.toString(CharsetUtil.UTF_8));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //发送消息给客户端
        ctx.writeAndFlush(Unpooled.copiedBuffer("服务端已收到消息", CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //发生异常,关闭通道
        ctx.close();
    }
}

    创建客户端启动类
package com.example.demo.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class MyClient {
    public static void main(String[] args) {
        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
        //创建bootStrap对象,配置参数
        Bootstrap bootstrap = new Bootstrap();
        //设置线程组
        bootstrap.group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new MyClientHandler());
                    }
                });
        System.out.println("客户端就绪");
        try {
            ChannelFuture sync = bootstrap.connect("127.0.0.1", 6666).sync();
            sync.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            eventExecutors.shutdownGracefully();
        }

    }
}

    创建客户端处理器
package com.example.demo.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.EventExecutorGroup;

public class MyClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //发送消息到服务端
        ctx.writeAndFlush(Unpooled.copiedBuffer("你好", CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("收到服务端" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8));
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/727794.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号