netty源码浅析-服务端数据接入

Netty源码分析系列之新连接的接入 当 netty 的服务端启动以后,就可以开始接收客户端的连接了。那么在 netty 中,服务端是如何来进行新连接的创建的呢? 阅读详情

服务端数据接入

//读事件和连接事件就绪,执行unsafe.read()
            //如果是boss线程则是OP_ACCEPT事件,如果是work线程则是OP_READ事件
            if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                unsafe.read();
            }

和上面的客户端接入类似,我们之前已经分析过了在ionetty.channelnio.NioEventLoop#processSelectedKey()中work线程主要处理客户端的的read和write事件,这里是work线程,我们跟进到unsaferead()方法,由于当前是work线程,所以会走到io.netty.channel.nio.AbstractNioByteChannel.NioByteUnsafe#read方法。

public final void read() {
            //channel配置类对象
            final ChannelConfig config = config();
            //pipeline
            final ChannelPipeline pipeline = pipeline();
            //byteBuf分配器
            final ByteBufAllocator allocator = config.getAllocator();
            //AdaptiveRecvByteBufAllocator内部HandleImpl
            final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
            //设置初始值
            allocHandle.reset(config);

            ByteBuf byteBuf = null;
            boolean close = false;
            try {
                do {
                    //创建一个默认大小1024的直接内存
                    byteBuf = allocHandle.allocate(allocator);
                    allocHandle.lastBytesRead(doReadBytes(byteBuf));
                    //如果最后一次没有读取到数据说明读取数据完毕
                    if (allocHandle.lastBytesRead() <= 0) {
                        // nothing was read. release the buffer.
                        //释放内存
                        byteBuf.release();
                        byteBuf = null;
                        //那什么时候doReadBytes(byteBuf)的值小于零呢
                        //1.客户端发送数据完毕并关闭连接
                        //2.客户端关闭了连接,发生异常返回-1
                        close = allocHandle.lastBytesRead() < 0;
                        //读取完毕
                        if (close) {
                            readPending = false;
                        }
                        break;
                    }
                    //记录读取的次数,最大默认为16次
                    allocHandle.incMessagesRead(1);
                    readPending = false;
                    pipeline.fireChannelRead(byteBuf);
                    byteBuf = null;
                } while (allocHandle.continueReading());

                allocHandle.readComplete();
                pipeline.fireChannelReadComplete();

                if (close) {
                    closeOnRead(pipeline);
                }
            } catch (Throwable t) {
                handleReadException(pipeline, byteBuf, t, close, allocHandle);
            } finally {
                if (!readPending && !config.isAutoRead()) {
                    removeReadOp();
                }
            }
        }
    }

我们将上面代码拆开来看

 //channel配置类对象
final ChannelConfig config = config();
//pipeline
final ChannelPipeline pipeline = pipeline();
//byteBuf分配器
final ByteBufAllocator allocator = config.getAllocator();
//AdaptiveRecvByteBufAllocator内部HandleImpl
final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
//设置初始值
allocHandle.reset(config);

可以看到首先获取ChannelConfig,这个config就是我们在创建NioServerSocketChannel时创建的 NioServerSocketChannelConfig,pipeline也是创建一起创建时创建的

 public NioServerSocketChannel(ServerSocketChannel channel) {
        //1.调用父类构造方法
        super(null, channel, SelectionKey.OP_ACCEPT);
        //2.创建配置类
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }

我们看下allocator的创建,跟踪一下config.getAllocator方法,来到了

public ByteBufAllocator getAllocator() {
        return allocator;
    }
private volatile ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;

allocator就是DefaultChannelConfig的属性,也就是在创建DefaultChannelConfig时就创建了,我们继续跟踪进入到ByteBufAllocator接口中,继续跟踪到ByteBufUtil中

ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;
static {
        //判断当前运行环境是不是安卓环境,如果是那就是非池化的
        String allocType = SystemPropertyUtil.get(
                "io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");
        allocType = allocType.toLowerCase(Locale.US).trim();

        ByteBufAllocator alloc;
        //默认创建的是池化内存
        if ("unpooled".equals(allocType)) {
            alloc = UnpooledByteBufAllocator.DEFAULT;
            logger.debug("-Dio.netty.allocator.type: {}", allocType);
        } else if ("pooled".equals(allocType)) {
            alloc = PooledByteBufAllocator.DEFAULT;
            logger.debug("-Dio.netty.allocator.type: {}", allocType);
        } else {
            alloc = PooledByteBufAllocator.DEFAULT;
            logger.debug("-Dio.netty.allocator.type: pooled (unknown: {})", allocType);
        }

        DEFAULT_ALLOCATOR = alloc;

        THREAD_LOCAL_BUFFER_SIZE = SystemPropertyUtil.getInt("io.netty.threadLocalDirectBufferSize", 64 * 1024);
        logger.debug("-Dio.netty.threadLocalDirectBufferSize: {}", THREAD_LOCAL_BUFFER_SIZE);

        MAX_CHAR_BUFFER_SIZE = SystemPropertyUtil.getInt("io.netty.maxThreadLocalCharBufferSize", 16 * 1024);
        logger.debug("-Dio.netty.maxThreadLocalCharBufferSize: {}", MAX_CHAR_BUFFER_SIZE);
    }

这里会判断当前运行的环境是不是安卓环境,如果是就创建非池化的内存,默认是创建池化的内存,关于池化非池化我们之后会在分析,如果平台支持直接内存,会申请直接内存。这点我们只需要知道起始就是申请了一块内存。我们继续回到io.netty.channelnio.AbstractNioByteChannelNioByteUnsafe#read方法,这里和上面分析的客户端连接接入相同,调用ionettychannelAdaptiveRecvByteBufAllocator#newHandle方法创建了内部类 Handlelmpl对象。并调用reset方法对一些属性设置初始值。

public void reset(ChannelConfig config) {
            this.config = config;
            maxMessagePerRead = maxMessagesPerRead();//16
            totalMessages = totalBytesRead = 0;
        }

下面我们继续分析read方法

ByteBuf byteBuf = null;
            boolean close = false;
            try {
                do {
                    //创建一个默认大小1024的直接内存
                    byteBuf = allocHandle.allocate(allocator);
                    allocHandle.lastBytesRead(doReadBytes(byteBuf));
                    //如果最后一次没有读取到数据说明读取数据完毕
                    if (allocHandle.lastBytesRead() <= 0) {
                        // nothing was read. release the buffer.
                        //释放内存
                        byteBuf.release();
                        byteBuf = null;
                        //那什么时候doReadBytes(byteBuf)的值小于零呢
                        //1.客户端发送数据完毕并关闭连接
                        //2.客户端关闭了连接,发生异常返回-1
                        close = allocHandle.lastBytesRead() < 0;
                        //读取完毕
                        if (close) {
                            // There is nothing left to read as we received an EOF.
                            readPending = false;
                        }
                        break;
                    }
                    //记录读取的次数,最大默认为16次
                    allocHandle.incMessagesRead(1);
                    readPending = false;
                    pipeline.fireChannelRead(byteBuf);
                    byteBuf = null;
                } while (allocHandle.continueReading());

首先会根据上面创建的allocator创建一块内存大小默认为1024的直接内存,然后调用doReadBytes开始读取数据写入内存,我们跟踪一下doReadBytes方法

protected int doReadBytes(ByteBuf byteBuf) throws Exception {
        final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();//handleImpl
        //byteBuf中可以读取的内容大小
        allocHandle.attemptedBytesRead(byteBuf.writableBytes());
        //读取数据到byteBuf
        return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
    }

这里将数据读取到我们上面申请的内存中,然后返回去读的字节数

public void lastBytesRead(int bytes) {
            lastBytesRead = bytes;//最后一次读取的字节长度
            if (bytes > 0) {
                //一共读取的字节长度
                totalBytesRead += bytes;
            }
        }

如果读取方法返回值为0说明数据读取尸经结束如果返回为-1说明客户端关闭了连接,则将内存释放,并跳出循环。然后记录读取到的message的数量,并将读取到的数据在pipeline中传递。我们看下跳出循环的条件是什么

public boolean continueReading(UncheckedBooleanSupplier maybeMoreDataSupplier) {
            //config.isAutoRead()默认为true
            return config.isAutoRead() &&
                    //respectMaybeMoreData默认为true
                   (!respectMaybeMoreData || maybeMoreDataSupplier.get()) &&
                    //已经读取到的总连接数是不是超过了maxMessagePerRead,默认是16
                   totalMessages < maxMessagePerRead &&
                    //totalBytesRead设置为0,一直为false
                   totalBytesRead > 0;
        }

我们分开来看这 几个条件

  • config.isAutoRead():默认为true
  • (lrespectMaybeMoreDatamaybeMoreDataSupplierget():respectMaybeMoreData默认为true,这里主要关注的是maybeMoreDataSupplierget()的返回值,我们看一下起始就是比较attemptedBytesRead== lastBvtesRead是否相等attemptedBytesRead就是我们在读取的时候设置的值,起始就是bytebuf可以读取的字节数量,lastBytesRead是每次去读的自己字节数,也就是如果他们俩相等,则说明我们申请的bytebuf直接被读满了,也就是还有数据没有读完,如果不相等,则申请的内存足够读取数据,数据已经读取完毕。
  • totalMessages<maxMessagePerRead:判断读取的总的message数量不能超过最大值,默认为16个,这里最多16次可能是为了不想延迟太久,其他的channel传输的数据没有办法得到处理。
  • totalBytesRead>0:如果读取到数据则totalBytesRead的值总是大于0
    这里可以看到会判断我们申请的内存是不是被读取满了,如果是则可能数据还没有读取完毕,则再执行一次循环重新申请内存在读取一次,并且读取的message的数量不能超过16次。我们继续分析
allocHandle.readComplete();
pipeline.fireChannelReadComplete();

if (close) {
    closeOnRead(pipeline);
}

我们跟踪readComplete方法进入io.netty.channel.AdaptiveRecvByteBufAllocator.HandleImpl#readComplete方法

 public void readComplete() {
            record(totalBytesRead());
        }
private void record(int actualReadBytes) {
            //判断我们读取的字节数和SIZE_TABLE数组中index对应位置的前一个位置的大小进行比较
            //如果比这个值小说明需要缩容
            if (actualReadBytes <= SIZE_TABLE[max(0, index - INDEX_DECREMENT - 1)]) {
                if (decreaseNow) {
                    index = max(index - INDEX_DECREMENT, minIndex);
                    //获取缩容后的大小
                    nextReceiveBufferSize = SIZE_TABLE[index];
                    decreaseNow = false;
                } else {
                    //将缩容标志位设置未true,等待下次进行扩展
                    decreaseNow = true;
                }
                //如果读取的数据大小大于分配值则需要扩容
            } else if (actualReadBytes >= nextReceiveBufferSize) {
                index = min(index + INDEX_INCREMENT, maxIndex);
                nextReceiveBufferSize = SIZE_TABLE[index];
                decreaseNow = false;
            }
        }

这里我们知道AdaptiveRecvByteBufAllocator是 个弹性的内存分配 内部维护了分配内存大小的数组

static {
        List<Integer> sizeTable = new ArrayList<Integer>();
        //如果内存大小小于512则按照每次递增16
        for (int i = 16; i < 512; i += 16) {
            sizeTable.add(i);
        }
        //如果大于512每次扩展2倍
        for (int i = 512; i > 0; i <<= 1) {
            sizeTable.add(i);
        }

        SIZE_TABLE = new int[sizeTable.size()];
        for (int i = 0; i < SIZE_TABLE.length; i ++) {
            SIZE_TABLE[i] = sizeTable.get(i);
        }
    }

它会根据本次接收的文件大小来调整下次申请内存的大小,缩容或者是扩容,尽量可以刚好满足内存大小的分配然后触发pipelinefireChannelReadComplete(),传递ReadComplete事件。最后如果发送数据过程中,客户端发送异常关闭了这个连接,则执行一些关闭channel的操作。到这里我们分析完了服务端接收数据的过程。如果有分析错误的地方还请不吝指正。感谢!!!

如何修复Windows卡在“正在准备Windows”的问题?这里有详细步骤 如何修复Windows卡在“正在准备Windows”的问题?这里有详细步骤。 阅读详情

相关推荐

FFmpeg HDR视频转SDR视频命令

之前蓝光盘电影多是AVC 1080p 8bit SDR格式视频,近两年4K电影流行,下载的蓝光电影多是HEVC 2160p 10bit HDR视频格式。 ffprobe查看有如下属性: # 10bit HDR Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x2160 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98

彼此当年少,莫负好时光 1万+

Netty学习笔记内存管理篇:内存分配ByteBufAllocator

此接口来进行实际的内存分配,默认使用的是ByteBufAllocator.DEFAULT,初始化时会根据配置和平台进行赋值。 io.netty.allocator.type可以设置为unpooled和pooled指定是否需要缓冲池,如果不设置则会根据平台判断。逻辑如下: static { String allocType = SystemPropertyUtil.get( ...

船长 3175

数学概念 | 旋转矩阵、欧拉角、四元数

旋转矩阵、欧拉角、四元数概念及相关运算;

NapoleonCoder的博客 771

java代码实现Netty中的Buffer写入Channel中的数据

Netty、NIO、 Buffer 、channel

qq_51715571的博客 1087

运放实现阶梯波发生器-总结报告

实验目的: 学习、理解、掌握方波电路、限幅电路积分累加电路、反馈电路 课程条件: 电脑仿真软件Multisim 原理框图和实验思路: 方波电路通过微分电路可以形成正负脉冲,在通过限幅电路后变为单脉冲,最后在积分电路中形成阶梯波。微分电路存在的意义就是为了防止方波频率过大,从而导致在经过限幅电路的方波,在一个周期内将电容的电充满,这样就不会产生阶梯波。如果方波的频率比较小,可以近似认为是正负脉冲,这样就可以跳过微分电路。 ...............

0 1万+

我写了一个自动识别火车车厢位置的算法【lidar点云识别】

我写了一个自动识别火车车厢位置的算法【lidar点云识别】

qq_43212290的博客 797

netty源码:(48) ChannelHandlerContext的alloc方法得到的ByteBufAllocator类型是如何确定的?

也就是默认使用DirectByteBuf,如果设置了io.netty.noPreferDirect参数,则以这个参数为准,如果设置为true,则会使用HeapByteBuf。最终会返回UnpooledByteBufAllocator.DEFAULT或者PooledByteBufAllocator.DEFAULT.看是pooled还是unpooled,如果没有,则判断是否是安卓平台,是的话取unpooled,否则取pooled.首先获取io.netty.allocator.type(可按下图配置)

amadeus_liu2的博客 533

Python中的join函数的用法

从语法、实例、应用三方面详尽地介绍join函数

阿黎逸阳的博客 2万+

Netty 服务 接收新数据

Netty服务如何接收新的数据

炫的博客 2万+

[QMT和ptrade量化交易小白入门]-112、小市值热点概念交易策略,回测5年20倍

本专栏主要是介绍QMT和ptrade的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写200篇左右。QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。

木头大左的博客 1078

ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(二)

本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析,并进行概括总结。 本系列文章共包含六篇文章,前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_client.cpp等源码实现文件中全部函数的详细介绍,第六篇文章进行概括总结,包含自主探索功能包explore_lite的简介,实现未知环境自主探索功能的原理及流程总结,效果演示,使用功能包exp

慕羽★的博客 1647

Netty如何高效接收网络数据?一文聊透ByteBuffer动态自适应扩缩容机制

本文介绍了Netty如何高效接收网络连接全流程并深入剖析了ByteBuffer动态自适应扩缩容机制。阐述了为什么会使用堆外内存来为ByteBuffer分配内存,由此引出了Netty的内存池PooledByteBufAllocator

bin的技术小屋 1240

128、点云配准与ICP:经典配准算法与深度学习配准

上周调试一台双臂协作机器人,左手持结构光相机扫描桌面上的随机堆叠工件,右手准备执行抓取。问题出在“对齐”这一步——相机扫描得到的点云和CAD模型点云之间差了大约15度的旋转,导致抓取姿态计算出来直接怼到桌面上。我第一反应是“ICP跑一下不就行了”,结果跑了三分钟,误差纹丝不动,甚至越迭代越发散。后来查了日志才发现,初始位姿给得太离谱,ICP直接掉进了局部最优。这个场景太典型了——很多人以为点云配准就是调个ICP库函数,实际工程里坑比想象中多得多。今天这篇笔记,咱们把点云配准这件事从头捋一遍。

sundong_81的博客 42

netty源码学习之服务端客户端初始化

本篇博文从netty的使用例子出发,服务端bind()方法和客户端的connect()方法,分别分析了一下netty服务端和客户端的建立过程(大量篇幅),最终给予对上述理解简要总结了一次基于netty的一次请求和响应过程图解,希望对大家学习netty知识有所帮助,如果帮到你的话希望点赞、转发、一键三连让我们一起在技术的海洋遨游,奥利给!!!

liushangzaibeijing的博客 5万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Netty Review - 服务端channel注册流程源码解析

当有新的连接接入时,会触发ACCEPT事件,EventLoop会调用相关的ChannelHandler进行处理,如调用ChannelInitializer的initChannel方法,添加用户自定义的ChannelHandler到新的连接的ChannelPipeline中。接着,新的连接就可以接受和处理客户端的请求了。当一个连接被注册到某个 Worker 线程池的 EventLoop 中时,该 EventLoop 将负责处理这个连接的所有事件,包括读取数据、写入数据、处理网络事件等。

小工匠 8125

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Netty源码—服务端启动流程

用户调用启动辅助类ServerBootstrap的bind()方法时,第一步通过反射创建服务端Channel会执行NioServerSocketChannel的默认构造方法,来创建一个NioServerSocketChannel对象,并且在创建过程中会创建Netty的一系列核心组件:如Channel、ChannelConfig、ChannelId、Unsafe、ChannelPipeline。ServerBootstrap.bind() //用户代码入口。

sdgfafg_25的博客 1053

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Netty服务端的新连接接入源码解析

经过上一章节的学习,我们基本了解了Netty是如何对IO事件以及异步任务的处理了,今天我们就一起来学习一下,Netty是如何处理新连接接入与数据读取的! 一、源码寻找 我们上一章节学到了,当存在IO事件的时候,Netty的反应堆线程会监听这些事件,然后进行处理,忘记的,可以回顾一下上一章节,,我们这里直接进入到: io.netty.channel.nio.NioEventLoop#processSelectedKey(java.nio.channels.SelectionKey, io.netty.cha

皇甫嗷嗷叫 336

Netty服务端源码解析

Netty是一个基于Java NIO的网络编程框架,提供了简单而强大的API,用于快速开发可扩展的网络服务器和客户端应用程序。 Netty的设计目标是提供一个高性能、可维护、可扩展的网络编程框架。它的核心思想是通过提供异步事件驱动的网络应用程序开发模型,使得开发者可以轻松地构建高性能的网络应用程序。

子浩的博客 738

Netty源码—4.客户端接入流程一

第一部分是逐层调用父类的构造方法,其中会设置这个客户端Channel的阻塞模式为false,然后再把感兴趣的读事件OP_READ保存到这个Channel的成员变量中以便后续注册到Selector,接着会创建一系列的组件,包括作为Channel唯一标识的Id组件、用来进行底层数据读写的unsafe组件、用来作为业务逻辑载体的pipeline组件。Netty中最核心的是两种类型的Reactor线程,这两种类型的Reactor线程可以看作Netty中的两组发动机,驱动着Netty整个框架的运转。

mjunz的博客 1206

netty源码浅析-数据接入与解码过程

数据接入与解码过程 我们接着上面分析的服务端接收到数据后的处理,其中有一步是执行pipelinefireChannelRead(byteBuf)方法,将数据传递给后面的处理流程,我们看看后面的解码过程。我们继续跟踪这个方法会走到 io.netty.channel.DefaultChannelPipeline.HeadContext#channelRead public void channelRead(ChannelHandlerContext ctx, Object msg) throws Excepti

GeekerJava的博客 416

【Netty 从成神到升仙系列 一】Netty 服务端的启动源码剖析(一)

大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,Java领域新星创作者。这是我的系列专栏:Netty 从成神到升仙。如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步。如果感觉博主的文章还不错的话,请三连支持一下博主哦。......

爱敲代码的小黄 1737

Netty源码—1.服务端启动流程一

用户调用启动辅助类ServerBootstrap的bind()方法时,第一步通过反射创建服务端Channel会执行NioServerSocketChannel的默认构造方法,来创建一个NioServerSocketChannel对象,并且在创建过程中会创建Netty的一系列核心组件:如Channel、ChannelConfig、ChannelId、Unsafe、ChannelPipeline。Selector的轮询操作是由其绑定的EventLoop线程run()方法驱动的,在一个循环体内循环执行。

mjunz的博客 1201

Netty源码解析之服务端启动过程(一):服务端channel的形成和注册

本篇文章从源码角度详细跟踪了Netty服务端的启动过程

weixin_43274704的博客 1494

Netty 源码阅读 —— 服务端创建

之前项目中用过netty,这次趁着面试空闲时间,重新梳理一遍netty源码,从服务端创建开始,话不多说,直接上代码先看看netty服务端创建的整体代码,大概如下所示:public void bind(int port) throws Exception { EventLoopGroup workGroup = new NioEventLoopGroup(); EventLoopGr...

diu_brother的博客 1352

Netty原理与源码分析(4) - Netty源码解读之底层原理

假设客户端分别发送了两个数据包ABC和DEF给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4种情况1、服务端分两次读取到了两个独立的数据包,分别是ABC和DDEF,没有粘包和拆包;2、服务端一次接收到了两个数据包,ABC和DEF粘合在一起,被称为TCP粘包;3、服务端分两次读取到了两个数据包,第一次读取到了完整的ABC包和DEF包的部分内容(ABCD),第二次读取到了DEF包的剩余内容(EF),这被称为TCP拆包。

How - Liked | Blog 2036

Netty源码浅析

前言 到目前为止,已经看了不少框架的源码了,但如何对源码做笔记并写博客,不同框架适合的做笔记方式也不同 对于Netty框架而言,我认为以对比学习+回答问题的方式来浅析源码会好一些,因为Netty本质上也就是基于NIO的一个非阻塞网络编程框架,那么本篇笔记就对比一个简单的NIO非阻塞网络编程,看看Netty是如何实现的 流程解析 看Netty源码主要就是去看其如何实现Reactor模式的,关于Reactor的演变,在《初识Netty》中我做了对比,不进行赘述 本节主要比较一下NIO的传统非阻塞方式与Netty

DaHuangXiao的博客 701
上一篇: netty源码浅析-客户端接入
下一篇: netty源码浅析-数据接入与解码过程
胖柯G
博客等级 码龄10年 453粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值