Apache Modules编程中的bucket和brigade\桶队算法(bucket brigade algorithm)

2023-05-16

文章目录

    • Apache服务器传输数据的核心算法之桶队算法(bucket brigade algorithm)
    • 什么是网络流处理算法Bucket Brigad
    • Bucket Brigad算法使用场景
    • Bucket Brigade算法在开源产品中使用
    • Apache Modules编程中的bucket和brigade
      • 开源代码实例

Apache服务器传输数据的核心算法之桶队算法(bucket brigade algorithm)

水桶队(Bucket Brigade)是指一种消防技术,它通过人的链条将水引至火灾中。这种方法主要在机械化消防设备出现之前使用,在世界上一些不发达地区仍然可以使用。在这项技术中,一个人在水源附近装满一个水桶,水桶里的水可以用来灭火然后手把手地传递到最后一个扔到火上的人手中。水桶队仍然偶尔被用作消防演示和比赛的一个项目。

bucket
美: [ˈbʌkət]
英: [ˈbʌkɪt]
n. 吊桶;大量;(有提梁的)桶;水斗
v. 用桶装;〈美〉用桶打(水);〈英口〉催(马)猛奔
网络 水桶;铲斗;桶子

brigade
美: [brɪˈɡeɪd]
英: [brɪ’ɡeɪd]
n. 旅(陆军编制单位);(主张相同或其他某方面相似的)伙
v. 【军】把…编成旅;把…编成队[组]
网络 大队;班;大部队

Bucket Brigade 算法基于Bucket和Brigade的概念,是Apache服务器内部用来传输数据的算法。它通过创建一个包含多个Bucket的Brigade对象,并将其传递给下一个处理程序,从而实现对请求和响应数据流的管理和传输。

在Bucket Brigade算法中,每个模块可以使用Bucket API来创建和操作Bucket,然后将其添加到Brigade中。而Brigade则是由多个Bucket链接而成的链表结构,其中每个Bucket都有一个指向下一个Bucket的指针,这种链接方式类似于“接力棒”,因此得名Bucket Brigade

当请求或响应数据到达一个模块时,Bucket Brigade会将其打包为一个Brigade对象,并传递给下一个模块进行处理。下一个模块可以读取Brigade中的Bucket,并向其中添加新的Bucket,然后再将Brigade传递给下一个模块。这样,请求或响应数据就可以在一系列模块之间流动,并逐步被处理和修改,最终返回给客户端。

因此,Bucket Brigade算法与Bucket和Brigade密切相关,是Apache服务器传输数据的核心算法之一。在apache中,Bucket Brigade算法是一种用于处理HTTP请求的技术,其主要目的是在不从客户端接收完整请求的情况下将请求传递给Web服务器。

什么是网络流处理算法Bucket Brigad

网络流处理算法Bucket Brigade是一种基于Bucket Brigade传统概念的优化算法,它用于解决网络流问题。网络流问题是指在一个有向图中,从源节点到汇节点之间的最大或最小流量问题。

Bucket Brigade算法将网络流问题转化为多阶段的装载-卸载过程。它将每个节点看作一个桶,桶的容量表示节点的流量限制。算法从源节点开始,将数据通过每个节点(即桶)进行传递,并将数据带入目标节点(即汇节点)。不同于其他网络流处理算法,Bucket Brigade算法通过对数据进行拆分和合并来实现流量的平衡。

具体地说,Bucket Brigade算法使用了两个遗传算法操作:交叉和变异。在交叉操作中,算法从一个桶中选择一个元素,并将其插入到另一个桶中。在变异操作中,算法随机地改变一个元素在其所在的桶中的位置。这样在多次迭代后,算法能够找到一个最优的流量分配方案。

Bucket Brigade算法在解决网络流问题时表现出了较好的效果。它可以在较短时间内找到一个接近最优解的解决方案,并且能够处理大规模的网络流问题。

Bucket Brigad算法使用场景

Bucket Brigade算法是一种用于处理网络流的算法,它可以用于解决诸如路由、负载均衡和防火墙等问题。Bucket Brigade算法不依赖于Apache模块开发场景,也可以在其他网络应用中使用。

在路由方面,Bucket Brigade算法可以实现基于内容的路由,根据目标地址和请求内容来选择最佳的服务器进行响应。在负载均衡方面,Bucket Brigade算法可以帮助将流量尽可能平均地分配到可用的服务器上,从而提高系统的吞吐量和可靠性。在防火墙方面,Bucket Brigade算法可以协助检测和过滤网络流量中的恶意请求,从而保护网络安全。

总之,Bucket Brigade算法是一种通用的网络流处理算法,可以在各种网络应用中使用,并能够提高网络性能和安全性。

Bucket Brigade算法在开源产品中使用

  1. Apache Traffic Server:Apache Traffic Server是一个高性能的代理服务器和缓存,使用Bucket Brigade算法来提高网络性能和可靠性。
  2. NGINX:NGINX是一个流行的Web服务器和反向代理,使用Bucket Brigade算法来加速HTTP请求和响应处理。
  3. HAProxy:HAProxy是一种开源的负载均衡器和代理服务器,使用Bucket Brigade算法来平衡流量并提高系统的可伸缩性。
  4. Varnish Cache:Varnish Cache是一个高性能的HTTP加速器和反向代理,使用Bucket Brigade算法来提高响应速度和减少延迟。
  5. Squid Cache:Squid Cache是一个流行的代理缓存服务器,使用Bucket Brigade算法来提高请求和响应处理的效率。

总之,Bucket Brigade算法是一个通用的网络流处理算法,被广泛应用于各种开源产品中,并且已经被证明可以显著提高网络性能和可靠性。

Bucket Brigade算法并不仅限于HTTP场景,它可以用于任何需要处理网络流的情况。除了HTTP协议,Bucket Brigade算法还可以应用于TCP、UDP等协议上。

例如,在TCP和UDP协议中,Bucket Brigade算法可以帮助实现数据包的拆分和合并,从而提高传输效率和可靠性。在SSH、FTP等应用中,Bucket Brigade算法可以帮助传输文件和命令,并提高数据传输的速度和稳定性。

Bucket Brigade算法的优点是可以快速处理大量的网络数据流,同时还能够有效地减少内存消耗和CPU负载,因此在各种网络应用中都有应用前景。

Apache Modules编程中的bucket和brigade

bucket和brigade在Filter的开发中是必须要搞明白的东西。在Apache2.x的输出Filter中,Apache采用的块方式传递数据给每个Filter。

Bucket是Apache服务器处理请求和响应时内部传输数据的基本单元。它可以包含任何类型的数据,并且可以被链接到其他的Bucket来构建数据流。常见的Bucket包括文件、字符串、头信息、EOS(end of stream)等。

Brigade则是一个Bucket的集合,它们按照特定的顺序组成了一条数据链。这条链可以在各个模块之间传递,实现对请求或响应的处理。Brigade通常由三种类型的Bucket组成:Input Bucket、Output Bucket 和 Control Bucket。Input Bucket 用于存储请求数据,而 Output Bucket 用于存储响应数据。Control Bucket 则用于控制数据流的行为,如修改内容或结束数据流的传输。

在Apache Modules编程中,处理请求和响应的模块可以向Brigade中添加Bucket,并对其中的Bucket进行读取和写入操作,从而实现对请求或响应的处理。

在 Apache 中,每个请求都有两个 filter 链:一个输入过滤器链和一个输出过滤器链。这些 filter 链可以用来对请求和响应进行各种修改操作,如压缩、加密、解压缩等。

当 Apache 处理输入数据时,它会将数据交给 input filter 链上的第一个 filter 进行处理,随后经过一系列 filter 处理后最终到达 handler。而在处理输出数据时,则是先由 handler 生成输出内容,再通过 output filter 链上的一系列 filter 进行处理后发送给客户端。

Apache根据Content Handler产生内容的大小(目前是固定的切分),把输出流按照一定规则切分成1个大块,用brigade封装(由1个以上buckets组成)。

过滤器用来对 server 收到/发送的数据进行再加工。过滤器分两种:input filters 用于处理 server 从 client 收到的数据,output filters 用于处理 server 向 client 发送的数据。一个数据流上可以挂多个过滤器。这些过滤器可以通过显式指定来确定执行顺序。

bucket其实就是一个数据块,brigade其实就是把一系列bucket串起来的双向链表环,我们知道每次传给Filter一个块的时候,我们经常需要删除其中的数据、插入数据、移动数据、修改数据,每次数据操作完之后都要维护其链表不被破坏,这些都是由brigade来维护的,bucket是一个具体的数据操作对象。

brigade是一个链表,bucket是链表中的节点,brigade负责维护链表,bucket负责一个小块数据的生命周期。

bucket才是负责具体小块数据生命周期的,所以当我们遍历bridage中的一系列bucket的时候,每个bucket不一定已经准备好数据,所以我们必须要进行一次读取操作(其实质就是调用一次bucket指向的read方法)。

过滤器所加工的数据,存储在一种称为 桶 bucket 的容器中。 bucket 的实际存储可以是 文件\管道(pipe)\流(socket stream )堆内存(heap)甚至是栈内存(stack)。apache 提供了apr_bucket_read 方法,将 bucket 中的数据读取到用户指定的内存中。

开源代码实例

modsecrity v2.9.7 源码:
apache2\apache2_io.c

/**
 * Reads request body from a client.
 */
apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
    request_rec *r = msr->r;
    unsigned int finished_reading;
    apr_bucket_brigade *bb_in;
    apr_bucket *bucket;

    if (error_msg == NULL) return -1;
    *error_msg = NULL;

    if (msr->reqbody_should_exist != 1) {
        if (msr->txcfg->debuglog_level >= 4) {
            msr_log(msr, 4, "Input filter: This request does not have a body.");
        }
        return 0;
    }

    if (msr->txcfg->reqbody_access != 1) {
        if (msr->txcfg->debuglog_level >= 4) {
            msr_log(msr, 4, "Input filter: Request body access not enabled.");
        }
        return 0;
    }

    if (msr->txcfg->debuglog_level >= 4) {
        msr_log(msr, 4, "Input filter: Reading request body.");
    }
    if (modsecurity_request_body_start(msr, error_msg) < 0) {
        return -1;
    }

    finished_reading = 0;
    msr->if_seen_eos = 0;
    bb_in = apr_brigade_create(msr->mp, r->connection->bucket_alloc);
    if (bb_in == NULL) return -1;
    do {
        apr_status_t rc;

        rc = ap_get_brigade(r->input_filters, bb_in, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN);
        if (rc != APR_SUCCESS) {
            /* NOTE Apache returns AP_FILTER_ERROR here when the request is
             *      too large and APR_EGENERAL when the client disconnects.
             */
            switch(rc) {
                case APR_INCOMPLETE :
                    *error_msg = apr_psprintf(msr->mp, "Error reading request body: %s", get_apr_error(msr->mp, rc));
                    return -7;
                case APR_EOF :
                    *error_msg = apr_psprintf(msr->mp, "Error reading request body: %s", get_apr_error(msr->mp, rc));
                    return -6;
                case APR_TIMEUP :
                    *error_msg = apr_psprintf(msr->mp, "Error reading request body: %s", get_apr_error(msr->mp, rc));
                    return -4;
                case AP_FILTER_ERROR :
                    *error_msg = apr_psprintf(msr->mp, "Error reading request body: HTTP Error 413 - Request entity too large. (Most likely.)");
                    return -3;
                case APR_EGENERAL :
                    *error_msg = apr_psprintf(msr->mp, "Error reading request body: Client went away.");
                    return -2;
                default :
                    *error_msg = apr_psprintf(msr->mp, "Error reading request body: %s", get_apr_error(msr->mp, rc));
                    return -1;
            }
        }

        /* Loop through the buckets in the brigade in order
         * to extract the size of the data available.
         */
        for(bucket = APR_BRIGADE_FIRST(bb_in);
                bucket != APR_BRIGADE_SENTINEL(bb_in);
                bucket = APR_BUCKET_NEXT(bucket))
        {
            const char *buf;
            apr_size_t buflen;

            rc = apr_bucket_read(bucket, &buf, &buflen, APR_BLOCK_READ);
            if (rc != APR_SUCCESS) {
                *error_msg = apr_psprintf(msr->mp, "Failed reading input / bucket (%d): %s", rc, get_apr_error(msr->mp, rc));
                return -1;
            }

            if (msr->txcfg->debuglog_level >= 9) {
                msr_log(msr, 9, "Input filter: Bucket type %s contains %" APR_SIZE_T_FMT " bytes.",
                        bucket->type->name, buflen);
            }

            /* Check request body limit (should only trigger on chunked requests). */
            if (msr->reqbody_length + buflen > (apr_size_t)msr->txcfg->reqbody_limit) {
                if((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT)) {
                    *error_msg = apr_psprintf(msr->mp, "Request body is larger than the "
                            "configured limit (%ld).", msr->txcfg->reqbody_limit);
                    return -5;
                } else if((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL)) {

                    *error_msg = apr_psprintf(msr->mp, "Request body is larger than the "
                            "configured limit (%ld).", msr->txcfg->reqbody_limit);

                } else if ((msr->txcfg->is_enabled == MODSEC_DETECTION_ONLY) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL)){

                    *error_msg = apr_psprintf(msr->mp, "Request body is larger than the "
                            "configured limit (%ld).", msr->txcfg->reqbody_limit);

                } else if ((msr->txcfg->is_enabled == MODSEC_DETECTION_ONLY) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT)){

                    *error_msg = apr_psprintf(msr->mp, "Request body is larger than the "
                            "configured limit (%ld).", msr->txcfg->reqbody_limit);

                } else  {

                    *error_msg = apr_psprintf(msr->mp, "Request body is larger than the "
                            "configured limit (%ld).", msr->txcfg->reqbody_limit);

                    return -5;
                }
            }

            if (msr->txcfg->stream_inbody_inspection == 1)   {
#ifndef MSC_LARGE_STREAM_INPUT
                msr->stream_input_length+=buflen;
                modsecurity_request_body_to_stream(msr, buf, buflen, error_msg);
#else
                if (modsecurity_request_body_to_stream(msr, buf, buflen, error_msg) < 0) {
                    return -1;
                }
#endif
            }

            msr->reqbody_length += buflen;

            if (buflen != 0) {
                int rcbs = modsecurity_request_body_store(msr, buf, buflen, error_msg);

                if (msr->reqbody_length > (apr_size_t)msr->txcfg->reqbody_limit && msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL) {
                    finished_reading = 1;
                }

                if (rcbs < 0) {
                    if (rcbs == -5) {
                        if((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT)) {
                            *error_msg = apr_psprintf(msr->mp, "Request body no files data length is larger than the "
                                    "configured limit (%ld).", msr->txcfg->reqbody_no_files_limit);
                            return -5;
                        } else if ((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL)) {
                            *error_msg = apr_psprintf(msr->mp, "Request body no files data length is larger than the "
                                    "configured limit (%ld).", msr->txcfg->reqbody_no_files_limit);
                        } else if ((msr->txcfg->is_enabled == MODSEC_DETECTION_ONLY) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_PARTIAL)) {
                            *error_msg = apr_psprintf(msr->mp, "Request body no files data length is larger than the "
                                    "configured limit (%ld).", msr->txcfg->reqbody_no_files_limit);
                        } else {
                            *error_msg = apr_psprintf(msr->mp, "Request body no files data length is larger than the "
                                    "configured limit (%ld).", msr->txcfg->reqbody_no_files_limit);
                            return -5;
                        }
                    }

                    if((msr->txcfg->is_enabled == MODSEC_ENABLED) && (msr->txcfg->if_limit_action == REQUEST_BODY_LIMIT_ACTION_REJECT))
                        return -1;
                }

            }

            if (APR_BUCKET_IS_EOS(bucket)) {
                finished_reading = 1;
                msr->if_seen_eos = 1;
            }
        }

        apr_brigade_cleanup(bb_in);
    } while(!finished_reading);

    apr_status_t rcbe = modsecurity_request_body_end(msr, error_msg);

    if (msr->txcfg->debuglog_level >= 4) {
        msr_log(msr, 4, "Input filter: Completed receiving request body (length %" APR_SIZE_T_FMT ").",
                msr->reqbody_length);
    }

    msr->if_status = IF_STATUS_WANTS_TO_RUN;

    return rcbe;
}

这段代码是一个名为“read_request_body”的函数,它从HTTP客户端读取请求正文。它有两个参数:一个名为“msr”的modsec_rec结构指针和一个指向char指针的指针“error_msg”。

该函数首先检查是否存在要读取的请求正文,并检查是否启用了请求正文访问。如果不是,则返回0。如果这些检查通过,则函数开始读取请求正文。

该函数设置了一个**桶队列以从客户端读取数据。然后它进入一个循环,直到所有数据都被读取为止。在循环的每次迭代中,它使用Apache的ap_get_brigade函数读取下一块数据。然后它检查brigade中的每个bucket并从中提取数据。**它还检查请求体的大小是否超过了配置的限制,并处理请求体过大的情况。

如果启用了stream_inbody_inspection配置,则该函数将请求正文存储在一个流缓冲区中以供检查。该函数还更新请求正文长度,并将请求正文存储在临时缓冲区中以进行进一步处理。

一旦所有数据都被读取,该函数清理bucket brigade,结束请求正文处理,并设置一个状态标志,表示函数已成功完成。它返回apr_status_t值,指示操作的结果。

APR_BRIGADE_SENTINEL是Apache Portable Runtime (APR)库中的一个宏,用于返回一个指向bucket brigade的哨兵元素。bucket brigade是一种用于在Apache中处理数据的特殊数据结构,在输入输出过滤器中广泛使用。

这个宏定义的作用是获取指向bucket brigade结尾的哨兵元素,方便遍历bucket brigade。在bucket brigade中,每个bucket都是一个带有数据的数据单元,而哨兵元素是一个特殊的、空的bucket,用于标志bucket brigade的结尾,通常被称为“哨兵bucket”。

因此, 在对bucket brigade进行循环遍历时,可以使用APR_BRIGADE_FIRST宏获取第一个bucket,然后通过不断访问APR_BUCKET_NEXT来得到下一个bucket,直到遍历到哨兵元素(APR_BRIGADE_SENTINEL),表示bucket brigade已经遍历完毕。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Apache Modules编程中的bucket和brigade\桶队算法(bucket brigade algorithm) 的相关文章

  • centos 安装Git-cola

    首先安装Git sudo yum y install git 找到 git all noarch 安装这个 sudo yum install git all noarch 61 61 61 61 61 61 61 61 61 61 61 6
  • C++继承总结

    继承的概念 继承机制是面向对象程序设计使代码可以复用的重要手段 xff0c 它允许程序员在保持原有类特性的基础之上进行其他扩展 xff0c 增加功能 xff0c 这样产生的新类 xff0c 称之为派生类 继承呈现了面向对象程序设计的层次结构
  • 读完《大数据时代》的一点儿心得

    工作一段时间之后 xff0c 总喜欢读读书 xff0c 这是多年养成下来的一个习惯 读书使人避恶 xff0c 读书使人向善 xff0c 读书使人聪慧 xff0c 读书使人高尚 xff0c 我们都是聪明人 xff0c 对吧 xff1f 哈哈哈
  • 产品管理精华:第十一,数据的思维方式

    xfeff xfeff 数量庞大 增长迅猛 种类多样的数据已经成为企业在大数据时代发展不得不面临的现实境况 这是挑战 xff0c 也是机遇 基于客户需求 xff0c 提供领先 全面 有效的解决方案 xff0c 帮助企业获取商业洞察力 xff
  • 产品管理精华:第十四,产品炼成?

    xfeff 最近一段时间在准备信息系统项目管理师 的考试 xff0c 在备考复习过程中 xff0c 通过系统学习和理解项目管理相关知识 xff0c 发现项目和产品管理联系很密切 项目过程是伴随着产品过程而生 我们先来了解一下项目的定义 xf
  • glib简单记录包括字符串,主循环,回调函数和xml解析

    一 将最近用到的glib字符串功能整理了下直接用程序记录比较好看懂 define MAX LEN 100 gchar demo char msg gchar pcfgfile 61 NULL para 61 NULL va list arg
  • 产品管理精华:第十六,品味

    美感是第一道关卡 xff0c 丑陋的数学在世界上无法生存 G H 哈代 xff0c 一个数学家的道歉 品味 xff0c 如今很少听到这个词了 xff0c 可能被一些新的 xff0c 流行的叫法替代了 很长一段时间 xff0c 谈论品味这玩意
  • 《产品管理精华》目录

    产品管理精华 目录 本文是这个目录 xff0c 可以快速找到你需要的内容 xff1a 产品管理精华 xff1a 第一 xff0c 谁是优秀的产品经理 xff1f 产品管理精华 xff1a 第二 xff0c 工具 xff0c 适合自己的最好
  • 电商分销的社交化运营实践

    最近一段时间专注于研究社交化的电商分销运营体系 xff0c 如何最大化利用碎片化社会资源来整合营销渠道 目前最有代表性的电商分销就是全民分销概念 xff0c 它的最大特点在于通过社交网络 xff08 大部分是通过微信商城开店 43 三级返佣
  • 《产品管理精华》序

    今日事 xff0c 今日毕 xff01 xff0c 说起来容易 xff0c 做起来难 知道为什么要去做一件事 xff0c 这样做了哪些人都受到实惠 xff0c 领悟生活的趣味 xff0c 自己是否也得到了快乐和满足 xff0c 每一份付出都
  • 个人简介

    经验丰富的产品设计师 xff0c 专门从事与产品设计相关的研究 趋势分析 理念探索和产品研发 专注于政策脉搏和市场趋势的研究 xff0c 成功研发多个互联网相关领域产品 xff0c 对移动互联网产品架构 运营管理有较为深入的管控能力 欢迎大
  • 产品管理精华:第一,谁是优秀的产品经理?

    34 人因为梦想而伟大 34 英格丽 褒曼 每个人的心中都有一个梦想 xff0c 梦想是美好的 xff0c 但是实现梦想的道路是曲折的 xff0c 无数人在实现梦想的道路上遭遇了无数曲折 xff0c 尽管如此 xff0c 他们依旧大步向前
  • 产品管理精华:第三,需求调研,从用户出发

    因为需要 xff0c 让我更加完美 佚名 产品经理都会遇到 客户 用户 这两个概念念 xff0c 它们谁更重要也一直争论不休 用户 近乎苛刻的需求可以不断产品体验和质量 xff0c 同时产品投入市场之后都会遇到变现这个问题 xff0c 总需
  • 第1章 概述--PADS的历史版本

    1986年 xff1a PADS PCB xff0c DOS操作系统 1989年 xff1a PADS Logic xff0c DOS操作系统 1990年 xff1a PADS 2000 xff0c DOS操作系统 1993年 xff1a
  • docker安装图形化界面

    分享第一份Java基础 中级 高级面试集合 Java基础 xff08 对象 43 线程 43 字符 43 接口 43 变量 43 异常 43 方法 xff09 Java中级开发 xff08 底层 43 Spring相关 43 Redis 4
  • 嵌入式软件开发岗面试题

    1 单片机IO口开漏输出和推挽输出有什么区别 xff1f 答 xff1a 开漏输出 xff1a 开漏输出只能输出低电平 xff0c 如果要输出高电平必须通过上拉电阻才能实现 就类似于三极管的集电极输出 推挽输出 xff1a 推挽输出既可以输
  • pytorch 查看模型结构 网络参数

    用法比较简单 xff0c 不过容易忘 xff0c 记录一下 假设已定义好模型 xff0c 名为model 查看模型结构 xff1a gt gt gt print model 查看网络参数 xff1a for name parameters
  • 【Linux网络编程】select函数实现TCP并发服务器

    I O多路复用 应用程序中同时处理 多路 输入输出流 xff0c 若采用 阻塞模式 xff0c 将得不到预期的目的 xff1b 若采用 非阻塞模式 xff0c 对多个输入进行轮询 xff0c 但又太浪费 CPU 时间 xff1b 若设置 多
  • 【校招】面试_华为_通用软件工程师_二面

    1 面试信息 面试形式 xff1a 视频面试 面试时间 xff1a 2020 03 25 11 30 00 AM 面试时长 xff1a 40分钟 面试职位 xff1a 软件技术开发部 通用软件工程师 xff08 无线网络产品线 通用软件开发
  • 你必须会的启发式搜索算法--A*算法

    一 算法原理 A 算法 xff0c 就是解决在一个平面 grid地图中寻找起点到终点的最短路径问题的算法 xff0c 类似于Dijkstra算法和BFS算法一样 xff0c 属于广度优先搜索 实际上它还是一个启发式搜索算法 xff0c 什么

随机推荐

  • C/C++/LINUX 资源网站

    C C 43 43 LINUX 资源网站 本博客记录学习 开发中常用的网站 http www cplusplus com c 43 43 官网 xff0c 包含c 43 43 介绍以及一些简单的使用样例 目前主要用来查询 STL 的使用 h
  • 焊接单片机最小系统板,驱动lcd1602

    今天分享一些我制作单片机最小系统板的过程以及遇到的问题和解决办法 本人萌新一枚 xff0c 写文章就是我们大家互相学习交流 之前学习的是郭天祥的tx 1c单片机 xff0c 书中的例程都写的差不多了 xff0c 就想着自己焊接一个最小系统板
  • [ROS]极简开发环境建立流程(新手适用)

    ROS开发环境的建立 一 前言二 操作系统环境1 Ubuntu2 VMWare 可选 三 ROS运行环境1 ROS2 ROS周边设置3 ROS开发包及帮助获取方式 四 ROS开发环境1 建立工作空间 workspace2 Original开
  • 伽马函数与贝塔函数的定义

    伽马函数 称以下函数 61 0
  • Linux kernel development

    这几天一直在读经典的linux入门书 Linux kernel development 第三版即LKD xff0c 这是我第一次读英文版的技术书 xff0c 颇有些高兴 之所以读 xff0c 一是因为学过操作系统的理论知识 xff0c 想看
  • Windows + Ubuntu20.04双系统详细安装教程

    Windows 43 Ubuntu20 04双系统安装 1 制作启动盘1 1 从ubuntu官网下载ubuntu ISO文件1 2 下载启动Rufus1 3 将ISO文件写入启动盘1 3 1 设备 xff08 Device xff09 1
  • 程序员的成长之路

    1 初识编程 清楚的记得2008年上大学 xff0c 当时学的第一门编程语言是汇编语言 xff0c 第一堂课上 xff0c 老师就说这个学科的挂科率是最高的 xff0c 大家做好心理准备 xff0c 后来证明 xff0c 这并不是下马威 x
  • 关于协方差矩阵的理解

    转载自 关于协方差矩阵的理解
  • ubuntu下vscode配置C++环境-clang

    之前一直采用gcc xff0c 说不上多好用 xff0c 一直在凑活 xff0c 一次偶然的机会听说了clangd xff0c 就尝试了clang作为前端 xff0c 还挺好用 xff0c 这里分享给大家 xff08 踩了很多坑bushi
  • PID控制系统阶跃响应图-参数整定过程,matlab代码真实可用

    PID控制系统阶跃响应图 参数整定过程 xff0c matlab代码真实可用 点个赞呗 clear all clc close all PID span class token operator 61 span span class tok
  • c语言 查找指定字符

    本题要求编写程序 xff0c 从给定字符串中查找某指定的字符 输入格式 xff1a 输入的第一行是一个待查找的字符 第二行是一个以回车结束的非空字符串 xff08 不超过80个字符 xff09 输出格式 xff1a 如果找到 xff0c 在
  • 解决 UP Squared* Grove 物联网开发套件和 Arduino Create* 的连接问题

    如果您发现采用默认方法无法连接 UP Squared 主板和 Arduino Create xff0c 可以尝试另外一种方法 xff1a 使用串行终端连接主板 请执行以下步骤 开始前须知 确保主板已连接至电源和以太网 xff0c 如下所示
  • 解决 UP Squared* Grove 物联网开发套件和 Arduino Create* 的连接问题

    如果您发现采用默认方法无法连接 UP Squared 主板和 Arduino Create xff0c 可以尝试另外一种方法 xff1a 使用串行终端连接主板 请执行以下步骤 开始前须知 确保主板已连接至电源和以太网 xff0c 如下所示
  • PX4无人机offboard开发之旅

    目录 xff08 随进度更ing xff09 无人机OFFBOARD开发仿真步骤思路 真机PX4固件刷新连接pre arm策略修改 相机 图片慢慢补 xff0c 进度慢慢更 无人机OFFBOARD开发 使用无人机进行风力发电机叶片自动巡检任
  • 尚硅谷-尚医通实战经验总结

    整个系统采用b2c的管理模式 xff0c 分为管理员系统和用户系统 xff08 直接商对客 xff09 1 后端整合Swagger进行技术测试 2 后端框架使用ssmp框架 3 logback和 log4j 作为日志实现框架 4 idea开
  • 什么是web3 | 区块链web3.0人才

    文章目录 一 Web31 什么是web3 xff1f 2 web3的dapp架构 二 区块链web3 0人才1 区块链开发技术栈2 欧易对人才的要求3 如何成为一名合格的智能合约高级工程师4 web3各个赛道5 链上数据分析师6 一些案例
  • Noise协议和Disco协议选型

    文章目录 Noise协议和Disco协议选型noise协议和disco协议有什么区别 xff1f noise协议和disco协议分别适用什么场景 Noise协议和Disco协议选型 noise协议和disco协议有什么区别 xff1f No
  • SQL注入语义分析库libinjection

    文章目录 SQL注入语义分析库libinjection什么是libinjectionlibinjection和正则表达式modsecurity 如何使用libinjectionModSecurity只用了libinjection防御sql注
  • 逆采样(Inverse Sampling)和拒绝采样(Reject Sampling)原理详解

    在蒙特卡罗方法中 xff0c 有一个关键的问题需要解决 xff0c 即如何基于概率密度函数去采的 n n n 个 x x x 的样本集 逆采样 Inverse Sampling 和拒绝采
  • Apache Modules编程中的bucket和brigade\桶队算法(bucket brigade algorithm)

    文章目录 Apache服务器传输数据的核心算法之桶队算法 xff08 bucket brigade algorithm xff09 什么是网络流处理算法Bucket BrigadBucket Brigad算法使用场景Bucket Briga