7.Netty

Netty
    介绍:是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,它提供了
           简单易用的api从网络处理代码中解耦业务逻辑。Netty完全基于NIO实现的,Netty是异步的。
    
    Netty健壮性、功能、性能、可定制性和可扩展性在同类框架都是首屈一指的。
    
    网站:http://ifeve.com/netty5-user-guide/
    
    Netty实现通信的步骤:
        1:创建两个NIO线程组,一个用于网络事件处理(接受客户端的连接),另一个则进行网络
          通信的读写。
        2:创建一个ServerBootstarp对象,配置Netty的一系列参数,如传出去数据的缓存
        3:创建一个实际处理数据的类ChannelInitializer,进行初始化的准备工作,比如设置接受传出
          数据的字符集、格式、已经实际处理数据的接口
        4:绑定端口,执行同步阻塞方法等待服务器端口启动即可
    
    Netty对Byte实现了优化,因为有两个指针
    
    TCP粘包、拆包问题
        1、应用程序write写入的字节大小大于套接口发送缓冲区的大小
        2、进行MSS大小的TCP分段
        3、以太网帧的payload大于MTU进行IP分片
        
    TCP粘包、拆包解决方案
        1、消息定长
        2、在包尾部增加特殊字符进行分割,例如回车
        3、将消息分为消息头和消息体,在消息头中包含表示消息总总长度的字段,然后进行业务处理
    
    Hetty解决粘包、拆包问题
        1、分隔符 DelimiterBasedFrameDecoder
            在Server类和Client类中initChannel方法中
                ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
                sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));
                //设置字符串形式的解码
                sc.pipeline().addLast(new StringDecoder());
                
                sc.pipeline().addLast(new ServerHandler());
                
            Server类
                public class Server {
                    public static void main(String[] args) throws InterruptedException {
                        //第一个线程组 是用于接收Client端连接
                        EventLoopGroup bossGroup = new NioEventLoopGroup();
                        //第二个线程组 适用于实际的业务处理操作的
                        EventLoopGroup workerGroup = new NioEventLoopGroup();
                        
                        //创建一个辅助类Bootstrap,就是对我们Server进行一系列的配置
                        ServerBootstrap b = new ServerBootstrap(); // (2)
                        //把两个工作线程组加入进来
                         b.group(bossGroup, workerGroup)
                         //我要指定使用NioserverSocketChannel这种类型的通道
                          .channel(NioServerSocketChannel.class)
                          //一定要使用childHandler去绑定具体的事件处理器
                          .childHandler(new ChannelInitializer<SocketChannel>() {
                              @Override
                            protected void initChannel(SocketChannel sc) throws Exception {
                                // TODO Auto-generated method stub
                                ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
                                sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));
                                sc.pipeline().addLast(new StringDecoder());
                                sc.pipeline().addLast(new ServerHandler());
                            }
                        });
                        
                         ChannelFuture f = b.bind(8765).sync();
                        
                         f.channel().closeFuture().sync();
                        
                         bossGroup.shutdownGracefully();
                         workerGroup.shutdownGracefully();
                    }
                }
            
            ServerHandler类
                public class ServerHandler extends ChannelHandlerAdapter{
                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                            String request = (String)msg;
                            System.out.println("Server:"+request);
                            //写给客户端
                            String response = "我是反馈的信息$_";
                            ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()))
                                .addListener(ChannelFutureListener.CLOSE);
                    }
                    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                        // TODO Auto-generated method stub
                        cause.printStackTrace();
                        ctx.close();
                    }
                }
            
            Client类
                public class Client {
                    public static void main(String[] args) throws Exception{
                        EventLoopGroup group = new NioEventLoopGroup();

                        Bootstrap b = new Bootstrap();
                        b.group(group)
                        .channel(NioSocketChannel.class)
                        .handler(new ChannelInitializer<SocketChannel>(){
                            @Override
                            protected void initChannel(SocketChannel sc) throws Exception {
                                // TODO Auto-generated method stub
                                ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
                                sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));
                                sc.pipeline().addLast(new StringDecoder());
                                sc.pipeline().addLast(new ClientHandler());
                            }
                        });

                        ChannelFuture cf1 = b.connect("127.0.0.1",8765).sync();

                        cf1.channel().writeAndFlush(Unpooled.wrappedBuffer("hello netty!$_".getBytes()));
                        cf1.channel().writeAndFlush(Unpooled.wrappedBuffer("hello netty!$_".getBytes()));

                        cf1.channel().closeFuture().sync();
                        group.shutdownGracefully();
                    }
                }
            
            ClientHandler类
                public class ClientHandler extends ChannelHandlerAdapter{
                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        try {
                            //do something msg
                            String data = (String)msg;
                            System.out.println("Client: " + data);
                            
                        } finally {
                            ReferenceCountUtil.release(msg);
                        }
                        
                    }
                    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                        // TODO Auto-generated method stub
                        cause.printStackTrace();
                        ctx.close();
                    }
                }
                
        2、FixedLengthFrameDecoder(定长)
            在Server类和Client类中initChannel方法中
                //设置定长字符串接收
                sc.pipeline().addLast(new FixedLengthFrameDecoder(5));
                //设置字符串的解码
                sc.pipeline().addLast(new StringDecoder());
                sc.pipeline().addLast(new ServerHandler());
    
Netty编解码技术
    编解码技术就是java序列化技术,目的:第一进行网络传输,第二对象持久化
    虽然我们可以使用java进行对象序列化,netty去传输,但是java序列化的硬伤太多,比如
        java序列化没法跨语言、序列化后码流太大、序列化性能太低等等
        
    主流框架:
        JBoss的Marshalling包
        goole的Protobuf
        基于Protobuf的Kyro
        MessagePack框架
        
    JBoss的Marshalling是一个java对象序列化包,对JDK默认的序列化框架进行了优化,但又保持
        跟java.io.Serializable接口的兼容,同时增加了一些可调的参数和附加特性
        
        在Server类和Client类中initChannel方法中
        sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
        sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
        sc.pipeline().addLast(new ReadTimeoutHandler(5));
        sc.pipeline().addLast(new ServerHandler());
        
        ServerHandler中
        Req req = (Req) msg;
        System.out.println("server:"+req.getId()+","+req.getName()+","+req.getRequestMessage());
        
        Resp resp = new Resp();
        resp.setId(req.getId());
        resp.setName(req.getName());
        resp.setResponseMessage(req.getRequestMessage());
        ctx.writeAndFlush(resp);
        
        MarshallingCodeCFactory类
        public final class MarshallingCodeCFactory {
            /**
             * 创建Jboss Marshalling解码器MarshallingDecoder
             * @return MarshallingDecoder
             */
            public static MarshallingDecoder buildMarshallingDecoder() {
                //首先通过Marshalling工具类的精通方法获取Marshalling实例对象 参数serial标识创建的是java序列化工厂对象。
                final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
                //创建了MarshallingConfiguration对象,配置了版本号为5
                final MarshallingConfiguration configuration = new MarshallingConfiguration();
                configuration.setVersion(5);
                //根据marshallerFactory和configuration创建provider
                UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
                //构建Netty的MarshallingDecoder对象,俩个参数分别为provider和单个消息序列化后的最大长度
                MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024);
                return decoder;
            }

            /**
             * 创建Jboss Marshalling编码器MarshallingEncoder
             * @return MarshallingEncoder
             */
            public static MarshallingEncoder buildMarshallingEncoder() {
                final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
                final MarshallingConfiguration configuration = new MarshallingConfiguration();
                configuration.setVersion(5);
                MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
                //构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
                MarshallingEncoder encoder = new MarshallingEncoder(provider);
                return encoder;
            }
        }
        
webSocket将网络套接字引入到了客户端和服务端,
    ws特点:
        单一的tcp连接,双方可通信
        对代理、防火墙和路由器透明
        无头部信息、Cookie和身份验证
        无安全开销
        通过ping\pong帧保持链路激活
        服务器可主动传递给客户端,不在需要客户端轮询

实践
    两台机器或者多台使用Netty进行通信
        第一种,使用长连接通道不断开的形式进行通信,服务器和客户端通道一直处于开启状态
        第二种,一次性批量提交数据,采用短连接方式
        第三种,使用特殊的长连接,在指定的时间内,没有通信就断开,下次通信在建立连接
            如何设置超时后关闭通道,关闭后又如何再次建立连接
                5秒钟关闭,server和Client都要设置
                sc.pipeline().addLast.(new ReadTimeoutHandler(5));
                关闭之后,Client开启一个线程去建立连接
                new Thread(new Runnable(){
                    public void run() {
                        try {
                            System.out.println("进入子线程");
                            ChannelFuture cf = c.getChannelFuture();//一个连接服务器方法
                            System.out.println(cf.channel().isActive());
                            System.out.println(cf.channel().isOpen());
                            //再次发送数据
                            Req request = new Req();
                            request.setId(""+4);
                            request.setName("pro"+4);
                            request.setRequestMessage("数据信息"+4);
                            cf.channel().writeAndFlush(request);
                            cf.channel().closeFuture().sync();
                            System.out.println("子线程结束");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
                
                
            客户端宕机时关闭通道,下次客户端重启之后再次建立连接,服务器宕机重启后,如何建立连接
    
    心跳检测
    
    Netty实现文件服务器上传下载
        相比Struts或springmvc,Netty上传下载支持大文件,异步,并发,性能好,非阻塞
        
    fastdfs支持小文件上传,hdfs支持大文件、断点续传
        
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值