`

mina read方法出现BufferUnderflowException异常的解决办法

    博客分类:
  • mina
阅读更多

现象: 先连续发几十个很小很小的包(<10 byte) 再突然发一个大小64byte的包 这时你会发现mina就会出现以下错误

java.nio.BufferUnderflowException
 at java.nio.HeapByteBuffer.get(Unknown Source)
 at org.apache.mina.core.buffer.AbstractIoBuffer.get(AbstractIoBuffer.java:419)
 at org.apache.mina.core.buffer.AbstractIoBuffer.get(AbstractIoBuffer.java:827)
 at com.labox.common.net.ProtocolHandler.messageReceived(ProtocolHandler.java:81)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:752)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:414)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$5(DefaultIoFilterChain.java:411)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:832)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain$HeadFilter.messageReceived(DefaultIoFilterChain.java:616)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:414)
 at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:408)
 at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:582)
 at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:542)
 at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:534)
 at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$7(AbstractPollingIoProcessor.java:532)
 at org.apache.mina.core.polling.AbstractPollingIoProcessor$Worker.run(AbstractPollingIoProcessor.java:861)

经过对mina的分析,这是由对包长度不对做成的(即,我们发的包长是大于64byte的,但他的byteBuffer大小只有64byte,当我们尝试读取第65个byte就会出现这个错误)

mina怎会出现这种错误的呢??是不是有什么配置可以调整

找到mina读取byte的方法AbstractPollingIoProcessor类的read(T session)

此方法源代码如下

  

private void read(T session) {
        IoSessionConfig config = session.getConfig();

        System.out.println("cap buffer size"+config.getReadBufferSize());//这句我自己加的
        IoBuffer buf = IoBuffer.allocate(config.getReadBufferSize());

        final boolean hasFragmentation =
            session.getTransportMetadata().hasFragmentation();

        try {
            int readBytes = 0;
            int ret;

            try {
                if (hasFragmentation) {
                    while ((ret = read(session, buf)) > 0) {
                        readBytes += ret;
                        if (!buf.hasRemaining()) {
                            break;
                        }
                    }
                } else {
                    ret = read(session, buf);
                    if (ret > 0) {
                        readBytes = ret;
                    }
                }
            } finally {
                buf.flip();
            }

            if (readBytes > 0) {
                session.getFilterChain().fireMessageReceived(buf);
                buf = null;

                if (hasFragmentation) {
                    if (readBytes << 1 < config.getReadBufferSize()) {
                        session.decreaseReadBufferSize();
                    } else if (readBytes == config.getReadBufferSize()) {
                        session.increaseReadBufferSize();
                    }
                }
            }
            if (ret < 0) {
                scheduleRemove(session);
            }
        } catch (Throwable e) {
            if (e instanceof IOException) {
                scheduleRemove(session);
            }
            session.getFilterChain().fireExceptionCaught(e);
        }
    }

 


 

经过对这段代码的分析终于发现问题所在了

大家注意if (readBytes > 0) 这个块下的代码

你不难发现

  

if (hasFragmentation) {
                    if (readBytes << 1 < config.getReadBufferSize()) {
                        session.decreaseReadBufferSize();
                    } else if (readBytes == config.getReadBufferSize()) {
                        session.increaseReadBufferSize();
                    }
                }

 

意思是if hasFragmentation==true

if 当前配置初始化ByteBuffer大小 > 当前读取包的平方 为 true 就把配置中初始化byteBuffer大小减半

else if 当前已读取字节==配置包初始化大小  为true时 把配置中初始化byteBuffer大小加倍 

接下来结合我出错的现象看看

当我接连发几十个小于10byte的包时,这时配置中的初始化ByteBuffer大小就为取小,默认最小为64byte

当我再发一个大于64byte的包,但整个ByteBuffer只有64byte,那就出错了。

接下来我们来修正这个问题

方法一:不要改变默认初始化byteBuffer大小,要修改mina的源码

找到org.apache.mina.transport.socket.nio.NioSocketSession 这个类的METADATA变量

把 new DefaultTransportMetadata()的第四个参数改成false就ok了

方法二:自己写read()方法中得到byteBuffer实例的方法

从read()方法看出,他得到byteBuffer实例是每次去请求的,如果我们在这里做一个cache,每次从cache中得到,自然byteBuffer的大小也是固定的,只要按自己业务最大包大小去开就可以了。

每个线程用一个自己的ByteBuffer实例,这样就不会有同步问题.

找到org.apache.mina.core.polling.AbstractPollingIoProcessor类中的read(T session)方法改成

  

static ThreadLocal readCache=new ThreadLocal();//这个是放ByteBuffer实例的cache

private void read(T session) {

IoBuffer buf=readCache.get();
if(buf==null){
 buf=IoBuffer.allocate(512);//512为包默认大小
 readCache.set(buf);
}else{
 buf.clear();
}

try {
    int readBytes = 0;
    int ret;

    try {
            ret = read(session, buf);
            if (ret > 0) {
                readBytes = ret;
            }
    } finally {
        buf.flip();
    }

    if (readBytes > 0) {
        session.getFilterChain().fireMessageReceived(buf);
    }
    if (ret < 0) {
        scheduleRemove(session);
    }
} catch (Throwable e) {
    if (e instanceof IOException) {
        scheduleRemove(session);
    }
    session.getFilterChain().fireExceptionCaught(e);
}

}

 

 

另外发现一篇说mina处理断包和粘包处理的

一.  解码方法
mina中有个内置类CumulativeProtocolDecoder是专门用来处理断包和粘包的。该类的api文档中有个实现的例子。
类org.apache.mina.filter.codec.CumulativeProtocolDecoder
public abstract class CumulativeProtocolDecoder extends ProtocolDecoderAdapter {
    private final AttributeKey BUFFER = new AttributeKey(getClass(), "buffer");

    public void decode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        if (!session.getTransportMetadata().hasFragmentation()) {       //用来判断是否还有分帧(断包)
            while (in.hasRemaining()) {
                if (!doDecode(session, in, out)) {
                    break;
                }
            }
            return;
        }
       
      ////处理断包,省略
      ............................................

    }

    //需要实现的方法
    protected abstract boolean doDecode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception;
}

CumulativeProtocolDecoder是一个抽象类,必须继承并实现其doDecode方法,用户自定义协议的拆分就应该写在doDecode方法中,下面的类MessageDecoder是一个实现的例子。MessageDecoder解码网络数据到一种有两字节长度头的自定义消息协议格式。
/**
 * 断包和粘包处理,处理后的消息为一个或多个完整的数据消息
 * @author blc
 */
public class MessageDecoder extends CumulativeProtocolDecoder {
    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.mina.filter.codec.CumulativeProtocolDecoder#doDecode(org.apache
     * .mina.core.session.IoSession, org.apache.mina.core.buffer.IoBuffer,
     * org.apache.mina.filter.codec.ProtocolDecoderOutput)
     */
    @Override
    protected boolean doDecode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        
        in.order(ServerConfig.ByteEndian);    //字节序, ServerConfig.ByteEndian = ByteOrder.LITTLE_ENDIAN
        
        //消息buf
        IoBuffer buf = IoBuffer.allocate(ServerConfig.MessageMaxByte);   //ServerConfig.MessageMaxByte 最大消息字节数
        buf.order(ServerConfig.ByteEndian);
        
        //考虑以下几种情况:
        //    1. 一个ip包中只包含一个完整消息
        //    2. 一个ip包中包含一个完整消息和另一个消息的一部分
        //    3. 一个ip包中包含一个消息的一部分
        //    4. 一个ip包中包含两个完整的数据消息或更多(循环处理在父类的decode中)

        if (in.remaining() > 1) {
            int length = in.getShort(in.position());
if (length < 4) {
                throw new ServerException("Error net message. (Message Length="+length+")");
            }
            if (length > ServerConfig.MessageMaxByte) {
                throw new ServerException("Error net message. Message Length("+length+") > MessageMaxByte("+ServerConfig.MessageMaxByte+")");
            }
            if (length > in.remaining()) return false;
            //复制一个完整消息
            byte[] bytes = new byte[length];
            in.get(bytes);
            buf.put(bytes);
            
            buf.flip();
            out.write(buf);
            return true;
        } else {
            return false;
        }
    }
}

二.  使用
将上面的解码器作为一个过滤器配置到mina中即可,在spring中的配置方法如下:
    <!-- 协议过滤器,包括解码和译码 -->
    <bean id="protocolCodecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
        <constructor-arg>
            <bean id="factory" class="server.ClientConnServer.MessageCodecFactory"></bean>
        </constructor-arg>
    </bean>
    <!-- 将协议过滤器配置到mina的过滤链中 -->
    <bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
        <property name="filters">
            <map>
                <entry key="protocolCodecFilter" value-ref="protocolCodecFilter" />
            </map>
        </property>
    </bean>
    <!-- 处理器 -->
    <bean id="clientConnHandler" class="server.ClientConnServer.ClientConnHandler" />
    <!-- socket接收器,接收客户端连接 -->
    <bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor" destroy-method="unbind">
        <!--        <property name="defaultLocalAddress" value=":161" />-->
        <property name="handler" ref="clientConnHandler" />
        <property name="reuseAddress" value="true" />
        <property name="filterChainBuilder" ref="filterChainBuilder" />
    </bean>


要配置协议过滤器,必须使用一个ProtocolCodecFactory ,下面是简单实现
public class MessageCodecFactory implements ProtocolCodecFactory {
    private final MessageEncoder encoder;
    private final MessageDecoder decoder;
    
    public MessageCodecFactory() {
        encoder = new MessageEncoder();
        decoder = new MessageDecoder();
    }

    /* (non-Javadoc)
     * @see org.apache.mina.filter.codec.ProtocolCodecFactory#getDecoder(org.apache.mina.core.session.IoSession)
     */
    @Override
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
        return decoder;
    }

    /* (non-Javadoc)
     * @see org.apache.mina.filter.codec.ProtocolCodecFactory#getEncoder(org.apache.mina.core.session.IoSession)
     */
    @Override
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
        return encoder;
    }
}

/**
 * 译码器,不做任何事情
 */
public class MessageEncoder extends ProtocolEncoderAdapter {

    /* (non-Javadoc)
     * @see org.apache.mina.filter.codec.ProtocolEncoder#encode(org.apache.mina.core.session.IoSession, java.lang.Object, org.apache.mina.filter.codec.ProtocolEncoderOutput)
     */
    @Override
    public void encode(IoSession session, Object message,
            ProtocolEncoderOutput out) throws Exception {
        //Do nothing
    }

}

转自http://blianchen.blog.163.com/blog/static/1310562992010101891522100/

分享到:
评论

相关推荐

    mina 2.0.7 (源码)

    因为自己最近做mina相关的二次开发,出现 mina read方法出现BufferUnderflowException错误 后来通过查找资料,发现最简单的办法就是修改源码里面的内容,所以就修改了下,希望能帮助到需要帮助的朋友

    基于Rtd 2796方案的4K显示器方案:支持多种接口,适用于民用及专业应用领域,原理图与源代码共享

    内容概要:本文详细介绍了Rtd 2796这款高性能4K显示器控制器的技术特点和应用场景。Rtd 2796支持多种显示接口,包括LVDS、VBO和eDP,适用于民用、工业、矿山和医疗等多个领域。文中通过具体的代码示例和技术细节,解释了如何配置这些接口以及它们的应用优势。此外,文章还探讨了硬件设计的关键点,如电源时序控制、信号完整性处理和硬件级画面拼接等功能。针对不同应用场景的需求,Rtd 2796提供了稳定的显示解决方案,并附带了详细的原理图和源代码,帮助开发者加快开发进度。 适合人群:电子工程师、硬件设计师、嵌入式开发人员、显示技术爱好者。 使用场景及目标:①民用领域:4K显示器、智能电视和平板电脑;②工业领域:工业自动化设备和控制面板;③矿山领域:矿山监控系统和设备显示屏;④医疗领域:医疗设备显示屏和手术室监控系统。目标是为用户提供稳定、高性能的4K显示解决方案。 其他说明:文章提供了丰富的技术细节和代码示例,有助于深入理解和实际应用。对于希望深入了解4K显示器技术和Rtd 2796控制器的读者来说,是一份极具价值的参考资料。

    Rust音频处理实战:CPAL库实现实时音频流处理.pdf

    文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 Rust 以内存安全、零成本抽象和并发高效的特性,重塑编程体验。无需垃圾回收,却能通过所有权与借用检查机制杜绝空指针、数据竞争等隐患。从底层系统开发到 Web 服务构建,从物联网设备到高性能区块链,它凭借出色的性能和可靠性,成为开发者的全能利器。拥抱 Rust,解锁高效、安全编程新境界!

    航天电磁阀单元化制造工艺与质量管控.pdf

    航天电磁阀单元化制造工艺与质量管控.pdf

    Go语言编译器优化:-gcflags参数深度解析手册.pdf

    文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 编译闪电般迅速,并发性能卓越,部署轻松简单!Go 语言以极简设计理念和出色工程性能,成为云原生时代的首选编程语言。从 Docker 到 Kubernetes,全球顶尖科技企业都在采用 Go。点击了解 Go 语言的核心优势、实战窍门和未来走向,开启高效编程的全新体验!

    基于python实现进行股票分析和选股+源码+项目文档+使用说明(毕业设计&课程设计&项目开发)

    基于python实现进行股票分析和选股+源码+项目文档+使用说明,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 使用python进行股票历史数据下载和分析选股。除了选股策略以外,其他都可公开。 git网站上有很多优秀开源量化平台项目。本项目与其他项目的区别是,本项目侧重于选股、回测所需数据的导入工作。有了历史数据和选股策略,选择哪个量化平台做回测都是很轻松的事情了。 业余编程水平,需求导向。才疏学浅,刚学python几个月时间。git主要作为云端git库使用。无任何解答服务。 力求选择最稳定可靠的数据获取方式。虽然网上有很多数据源平台,但都受制于“积分”、带宽、平台是否更新等,完全是把程序主动权交到了对方手里。因此本项目所有数据依靠本地通达信软件导出提供

    Rust异步定时任务:TokioCron调度器.pdf

    文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 Rust 以内存安全、零成本抽象和并发高效的特性,重塑编程体验。无需垃圾回收,却能通过所有权与借用检查机制杜绝空指针、数据竞争等隐患。从底层系统开发到 Web 服务构建,从物联网设备到高性能区块链,它凭借出色的性能和可靠性,成为开发者的全能利器。拥抱 Rust,解锁高效、安全编程新境界!

    《基于多策略融合的改进麻雀搜索算法(SCSSA)复现研究》

    内容概要:本文详细介绍了融合正余弦和柯西变异的改进麻雀搜索算法(SCSSA)的复现过程。主要内容包括五个方面的改进策略:折射反向学习策略初始化、正余弦算法改进发现者策略、自适应调整系数、改进搜索因子以及柯西变异改进加入者策略。文中提供了具体的Python代码示例,展示了如何实现这些改进策略,并通过23个基准测试函数验证了SCSSA相比传统SSA的优越性能。此外,还通过图表分析了改进策略因子和搜索步长因子的变化,进一步证明了SCSSA的有效性。 适合人群:对优化算法感兴趣的科研人员、算法开发者以及相关领域的学生。 使用场景及目标:适用于需要解决复杂优化问题的研究和应用场合,旨在提高算法的全局搜索能力和跳出局部最优的能力,从而更快更精确地找到最优解。 其他说明:文章不仅提供了详细的理论解释和技术实现,还包括了丰富的实验数据和图表分析,帮助读者更好地理解和掌握SCSSA的工作原理和优势。

    verilog I2c设计代码

    rtl/axis_fifo.v rtl/i2c_init.v rtl/i2c_master_axil.v rtl/i2c_master_wbs_8.v rtl/i2c_master_wbs_16.v rtl/i2c_master.v rtl/i2c_single_reg.v rtl/i2c_slave_axil_master.v rtl/i2c_slave_wbm.v rtl/i2c_slave.v tb/test_i2c_init.v tb/test_i2c_master_axil.vtb/test_i2c_master_wbs_8.v tb/test_i2c_master_wbs_16.v tb/test_i2c_master.v tb/test_i2c_slave_axil_master.v tb/test_i2c_slave_wbm.v tb/test_i2c_slave.v

    适用于所有人的生成式AI-吴恩达

    适用于所有人的生成式AI-吴恩达:对于英文不佳的同学可看中文版课件

    binzi56_algorithm-pattern-c_30952_1746371906469.zip

    binzi56_algorithm-pattern-c_30952_1746371906469

    基于Stackelberg博弈的光伏用户群定价模型:优化电量共享,提升运营商与用户共赢策略

    内容概要:本文探讨了如何通过Stackelberg博弈模型解决光伏用户群之间的电量共享问题。当前分布式光伏上网政策限制了用户间的电量共享,导致资源利用效率低下。文中提出了一个多买方-多卖方的格局,运营商作为主导者制定内部电价,用户作为跟随者根据电价调整用电需求和光伏电量供应。通过MATLAB实现了模型的关键部分,包括参数定义、定价策略、用户需求响应以及寻找博弈均衡点。实验结果显示,该模型不仅提高了运营商的收益,还显著提升了用户的用电效益和光伏电量共享水平。 适合人群:对分布式能源系统、智能电网、博弈论及其应用感兴趣的科研人员和技术开发者。 使用场景及目标:适用于研究和开发分布式能源系统的优化调度方法,旨在提高光伏用户群的电量共享效率,促进能源的有效利用。 其他说明:文中详细介绍了模型的具体实现步骤和关键代码片段,提供了丰富的实验数据支持结论。此外,还讨论了实际应用中可能出现的问题及解决方案。

    ​​基于Swin Transformer与ASPP模块的图像分类系统设计与实现​

    基于Swin Transformer与ASPP模块的图像分类系统设计与实现 本文介绍了一种结合Swin Transformer与空洞空间金字塔池化(ASPP)模块的高效图像分类系统。该系统通过融合Transformer的全局建模能力和ASPP的多尺度特征提取优势,显著提升了模型在复杂场景下的分类性能。 模型架构创新 系统核心采用Swin Transformer作为骨干网络,其层次化窗口注意力机制能高效捕获长距离依赖关系。在特征提取阶段,创新性地引入ASPP模块,通过并行空洞卷积(膨胀率6/12/18)和全局平均池化分支,实现多尺度上下文信息融合。ASPP输出经1x1卷积降维后与原始特征拼接,有效增强了模型对物体尺寸变化的鲁棒性。 训练优化策略 训练流程采用Adam优化器(学习率0.0001)和交叉熵损失函数,支持多GPU并行训练。系统实现了完整的评估指标体系,包括准确率、精确率、召回率、特异度和F1分数等6项指标,并通过动态曲线可视化模块实时监控训练过程。采用早停机制保存最佳模型,验证集准确率提升可达3.2%。 工程实现亮点 1. 模块化设计:分离数据加载、模型构建和训练流程,支持快速迭代 2. 自动化评估:每轮训练自动生成指标报告和可视化曲线 3. 设备自适应:智能检测CUDA可用性,无缝切换训练设备 4. 中文支持:优化可视化界面的中文显示与负号渲染 实验表明,该系统在224×224分辨率图像分类任务中,仅需2个epoch即可达到92%以上的验证准确率。ASPP模块的引入使小目标识别准确率提升15%,特别适用于医疗影像等需要细粒度分类的场景。未来可通过轻量化改造进一步优化推理速度。

    【38字】MATLAB代码:综合能源系统碳交易与电制氢的热电优化研究【80字】

    内容概要:本文探讨了基于MATLAB和CPLEX仿真平台实现的考虑阶梯式碳交易机制与电制氢的综合能源系统热电优化。研究围绕碳交易、电制氢、阶梯式碳交易、综合能源系统热电优化等关键概念展开。通过引入阶梯式碳交易机制,使综合能源系统能够更好地控制碳排放。同时,细化电制氢过程,引入电解槽、甲烷反应器、氢燃料电池等设备,提高了氢能的利用效率。此外,提出了热电比可调的热电联产及氢燃料电池运行策略,提升了系统的灵活性和经济性。最终,通过设置购能成本、碳排放成本、弃风成本最小的目标函数并利用CPLEX求解,实现了对综合能源系统的优化。 适合人群:从事能源系统优化、碳交易机制研究、氢能技术开发的研究人员和技术人员。 使用场景及目标:适用于希望深入了解如何通过MATLAB和CPLEX实现综合能源系统优化的人士。目标是掌握如何在考虑阶梯式碳交易机制和电制氢的情况下,优化热电联产系统的运行,以达到节能减排的目的。 其他说明:文中详细介绍了各个模块的具体实现方法,包括碳交易机制的融入、电制氢过程的细化、热电联产与氢燃料电池运行策略的制定,以及目标函数的构建和求解策略。

    图书馆管理系统源代码.zip

    图书馆管理系统源代码.zip

    西门子S7-1200控制五轴伺服程序案例:结构化编程技巧与多模式应用,包括脉冲定位、速度模式与扭矩模式,博图版本兼容性分析

    内容概要:本文详细介绍了西门子S7-1200控制器在5轴伺服控制系统中的应用案例。主要内容涵盖PTO伺服轴脉冲定位控制、速度模式和扭矩模式的具体实现方法。通过具体的PLC指令如MC_Power、MC_MoveAbsolute、MC_MoveVelocity等展示了如何精确控制伺服电机的位置、速度和扭矩。此外,文章强调了结构化编程和功能模块化设计的重要性,包括自动/手动/单步模式切换、暂停后原位置继续运行、轴断电保持以及报警处理等功能模块的设计思路。同时,文中还提到了程序的兼容性和功能块的复用性,使得程序易于维护和扩展。 适合人群:从事自动化控制领域的工程师和技术人员,尤其是那些希望深入了解西门子S7-1200控制器及其在多轴伺服控制中应用的人群。 使用场景及目标:①帮助工程师理解和掌握西门子S7-1200控制器在复杂多轴伺服控制中的编程技巧;②提供实际工程案例供参考,便于快速应用于类似的工程项目;③提高系统的稳定性和可靠性,确保在工业生产环境中高效运作。 其他说明:本文提供了丰富的代码片段和详细的解释,有助于读者更好地理解和实践。同时,文中提到的结构化编程思想和模块化设计理念对于提升编程效率和代码质量非常有价值。

    Go语言JWT认证:自定义Claims与刷新令牌方案.pdf

    文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 编译闪电般迅速,并发性能卓越,部署轻松简单!Go 语言以极简设计理念和出色工程性能,成为云原生时代的首选编程语言。从 Docker 到 Kubernetes,全球顶尖科技企业都在采用 Go。点击了解 Go 语言的核心优势、实战窍门和未来走向,开启高效编程的全新体验!

    【自然语言处理】基于Transformer架构的NLP核心技术解析与应用进展:从语言理解到多模态拓展

    内容概要:本文详细介绍了自然语言处理(NLP)及其核心技术Transformer的发展与应用。首先阐述了NLP的核心任务,包括语言理解(词法、句法、语义分析)、语言生成(文本摘要、对话系统等)和应用扩展(故障报告分析、情感分析等)。接着重点解析了2017年提出的Transformer模型,它摒弃传统RNN/CNN,采用自注意力机制,具有编码器-解码器结构和多头注意力机制,显著提升了长距离依赖建模能力,并衍生出BERT、GPT、T5等预训练模型。此外,还介绍了NLP的技术进展,如基于大规模语料库的自监督学习和微调机制,以及多模态拓展。最后提及了YOLO与NLP在特定资源包中的间接联系,强调当前NLP技术以Transformer为核心,持续推动语言智能边界。; 适合人群:对自然语言处理及Transformer技术感兴趣的科研人员、开发者及相关领域的学生。; 使用场景及目标:①了解NLP的基本概念和发展历程;②深入理解Transformer架构及其在NLP中的应用;③掌握NLP的关键技术进展和未来发展方向。; 其他说明:本文虽然提到YOLO,但主要聚焦于NLP与Transformer,YOLO仅在特定情况下与NLP存在间接关联。

    西门子PLC 1214C压机控制程序:模块化编程实现压装逻辑编辑与多功能块集成控制,支持触摸屏操作

    内容概要:本文详细介绍了基于西门子PLC 1214C的压机控制系统,重点展示了模块化编程的应用及其优势。文中涵盖了多个功能块的具体实现,如压机控制、伺服控制、气缸控制、托盘坐标计算、基恩士扫码器集成等。每个功能块均采用SCL语言编写,具备良好的可移植性和灵活性。通过模块化设计,实现了复杂系统的高效管理和快速响应,显著提升了开发效率和调试便利性。 适合人群:从事工业自动化控制、PLC编程以及相关领域的工程师和技术人员。 使用场景及目标:适用于需要进行压机控制或其他类似工业自动化项目的场合。主要目标是提高编程效率、增强系统的可维护性和灵活性,同时降低开发成本和缩短项目周期。 其他说明:文章还提供了具体的代码示例,帮助读者更好地理解和应用模块化编程思想。此外,强调了模块化编程在实际项目中的重要性和优越性,鼓励读者尝试并掌握这一先进的编程方法。

    欧姆龙NB系列触摸屏配方程序'NB-Designer':含宏功能,200个配方组,已测试可直接套用

    内容概要:本文详细介绍了欧姆龙NB系列触摸屏配方程序的设计方法,主要利用索引寄存器和宏功能来实现高效的配方管理和搜索功能。文中首先阐述了项目背景,即在自动化项目中不同产品或工况需要不同的参数设置,因此配方功能至关重要。接着介绍了NB-Designer这一专用设计软件的功能特点及其在配方程序开发中的优势。然后深入探讨了索引寄存器的作用,将其比喻成地址簿,能够快速定位配方数据,并给出了具体的伪代码示例展示如何通过索引寄存器访问不同配方组的数据。此外,还讲解了宏功能的具体实现方式,如配方号搜索和配方名称搜索,提供了详细的代码片段。最后总结了这套配方程序的优点,强调其在实际项目中的稳定性和高效性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些需要处理复杂配方管理和搜索功能的人群。 使用场景及目标:适用于需要频繁更改参数设置的自动化生产线,如食品加工、制药等行业。目标是提高生产效率,减少人工干预,确保配方数据的准确性和实时性。 其他说明:本文不仅提供了理论指导,还附带了大量实际代码示例,便于读者理解和应用。同时,作者分享了许多实践经验,如优化搜索性能、处理设备重启后的配方恢复等,有助于读者在实际项目中少走弯路。

Global site tag (gtag.js) - Google Analytics