C++ Boost.ASIO async_read_until 慢

2023-12-20

我遇到了一个不寻常的问题。我有一个 C++ Boost.ASIO Web 服务器,为了处理传入请求,我使用以下代码:

boost::asio::async_read_until(
    socket_,
    response_,
    "\r\n\r\n",
    boost::bind(
            &connection::handle_read_headers,
            shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
    )
);

(其中“socket_”是我的 boost::asio::ip::tcp::socket,“response_”是 boost::asio::streambuf)

我试图获取请求的标头,然后我稍后执行第二个 async_read_until ,其传输与从请求标头解析的“内容长度”完全匹配。问题是上面的代码在一个非常现代的服务器上需要 100-900 毫秒才能返回(从该读取块开始,直到调用 handle_read_headers() 为止)。传入的请求如下所示:

POST /load HTTP/1.1
host: www.mysite.com
Accept: */*
Accept-Encoding: gzip,deflate
Content-type: application/x-www-form-urlencoded
From: googlebot(at)googlebot.com
Origin: http://www.mysite.com
Referer: http://www.mysite.com/another-page/
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
X-Forwarded-For: 66.249.75.103
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Content-Length: 287
Connection: keep-alive

and-the-actual-content-is-here.... (287 bytes worth)

标头似乎以 \r\n\r\n 结尾,并且它在一直读取到 EOF 之前确实会触发 handle_read_headers() 函数(因此它不会读取整个页面) - 它实际上是在触发正则表达式。这些请求来自谷歌,所以我非常有信心它不会落后于他们。

为什么要花这么长时间才能回来,有什么我可以忽略的吗?我可能错过了 async_read_until 的其他捕获吗?

Thanks!

编辑/更新: 好吧,现在我很困惑。在尝试兆字节的建议时,我从streambuf切换到字符数组(不走运),然后我重构代码以使用async_read_some而不是async_read_until,然后手动扫描分隔符。我还将所有操作系统变量(sysctrl.conf)重置为默认值(以缩小可能性)。不幸的是,在使用相同的传入 POST 请求调用 handle_read() 时,我仍然在以下代码中看到 100-900 毫秒的延迟:

socket_.async_read_some(
    boost::asio::buffer(response_),
    boost::bind(
        &connection::handle_read,
        shared_from_this(),
        boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred
    )
);

其中response_现在是:

boost::array<char, 4096> response_;

无济于事(同样的 100-900 毫秒延迟)。这不可能是正常的——有什么想法吗?

编辑2: 根据 Rhashimoto 的建议,我启用了处理程序跟踪,并在日志中发现了这个奇怪的地方:

[2013-07-05 15:58:39 - Thread 7fae57e3f700]: Incoming connection (0ms elapsed)
@asio|1373054319.874916|506*508|[email protected] /cdn-cgi/l/email-protection_receive
@asio|1373054319.874963|506*509|[email protected] /cdn-cgi/l/email-protection_accept
@asio|1373054319.875008|<506|
@asio|1373054320.609088|>508|ec=system:0,bytes_transferred=512
@asio|1373054320.609233|508*510|[email protected] /cdn-cgi/l/email-protection_receive
@asio|1373054320.609264|<508|
@asio|1373054320.609284|>510|ec=system:0,bytes_transferred=404
[2013-07-05 15:58:40 - Thread 7fae57e3f700]: Received packet headers (638 bytes) - 734ms elapsed

async_accept 和 async_receive 之间有超过 700 毫秒的时间。在代码中,它来自这个块(实际上直接来自“HTTP Server 2”)http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples/cpp03_examples.html http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples/cpp03_examples.html- 服务器.cpp 和连接.cpp):

new_connection_->start();
new_connection_.reset(new connection(
        io_service_pool_.get_io_service()
));
acceptor_.async_accept(
        new_connection_->socket(),
        boost::bind(
                &server::handle_accept,
                this,
                boost::asio::placeholders::error
        )
);

从 start() 到:

void connection::start()
{
    boost::asio::async_read_until(
        socket_,
        response_,
        "\r\n\r\n",
        boost::bind(
            &connection::handle_read_headers,
            shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
        )
    );
}

当调用handle_read_headers()时,已经过去了700ms。

有人有什么想法吗?我完全迷路了。

非常感谢!


让我们看一下处理程序日志

[2013-07-05 15:58:39 - Thread 7fae57e3f700]: Incoming connection (0ms elapsed)
@asio|1373054319.874916|506*508|[email protected] /cdn-cgi/l/email-protection_receive
@asio|1373054319.874963|506*509|[email protected] /cdn-cgi/l/email-protection_accept
@asio|1373054319.875008|<506|
@asio|1373054320.609088|>508|ec=system:0,bytes_transferred=512
@asio|1373054320.609233|508*510|[email protected] /cdn-cgi/l/email-protection_receive
@asio|1373054320.609264|<508|
@asio|1373054320.609284|>510|ec=system:0,bytes_transferred=404
[2013-07-05 15:58:40 - Thread 7fae57e3f700]: Received packet headers (638 bytes) - 734ms elapsed

从日志中我们可以看到async_receive被调用两次:第一次在处理程序设置(#506)后 734 毫秒被调用(#508)。现在,第二个async_receive在处理程序设置 (#508) 后 53 微秒被调用 (#510)。就是这样,第二个处理程序调用的触发速度非常快,因为数据(这 404 字节)已经在 TCP 堆栈中准备就绪。

结论:这不是处理程序调用延迟,而是传输延迟。可能是 ISP 或平衡器出现问题,或者 Google 真的不想通过请求和设置延迟来打扰您。

UPD:我想你可以检查一下tcpdump

附:我不喜欢io_service_pool_HTTP 服务器 2 示例的实现。这也可能会导致一些问题,但我认为这不是当前的情况。

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

C++ Boost.ASIO async_read_until 慢 的相关文章

  • 用于代数简化和求解的 C# 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 网络上有很多代数求解器和简化器 例如 algebra com 上不错的代数求解器和简化器 然而 我正在
  • 使用 std::packaged_task/std::exception_ptr 时,线程清理程序报告数据争用

    我遇到了线程清理程序 TSan 的一些问题 抱怨某些生产代码中的数据争用 其中 std packaged task 通过将它们包装在 std function 中而移交给调度程序线程 对于这个问题 我简化了它在生产中的作用 同时触发 TSa
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 具有交替类型的可变参数模板参数包

    我想知道是否可以使用参数包捕获交替参数模式 例如 template
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • Azure 辅助角色“请求输入之一超出范围”的内部异常。

    我在辅助角色中调用 CloudTableClient CreateTableIfNotExist 方法 但收到一个异常 其中包含 请求输入之一超出范围 的内部异常 我做了一些研究 发现这是由于将表命名为非法表名引起的 但是 我尝试为我的表命
  • 如何禁用 fread() 中的缓冲?

    我正在使用 fread 和 fwrite 读取和写入套接字 我相信这些函数用于缓冲输入和输出 有什么方法可以在仍然使用这些功能的同时禁用缓冲吗 Edit 我正在构建一个远程桌面应用程序 远程客户端似乎 落后于服务器 我不知道可能是什么原因
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 不同类型指针之间的减法[重复]

    这个问题在这里已经有答案了 我试图找到两个变量之间的内存距离 具体来说 我需要找到 char 数组和 int 之间的距离 char data 5 int a 0 printf p n p n data 5 a long int distan
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看

随机推荐

  • 如何在 PHP 中克隆 gd 资源

    我正在寻找用 PHP 创建的克隆图像imagecreatetruecolor或其他一些图像创建功能 正如评论中所说 不 你不能做出像这样简单的感情 copy original 这是因为资源是引用 不能像标量值一样被复制 例子 a image
  • 用于获取标签列表的 GCP API

    是否有用于获取资源标签的 GCP API 我想要获取 GCP 项目的所有标签的列表 如何获取GCP中的所有标签 基本上 GCP 资源管理器 API 返回每个资源的 Lebel 对象 但我想使用一个 API 调用获取所有标签的列表 我尝试了下
  • 如何获取 numpy 数组中最大值的所有索引?

    我有一个数字数组 最大值可能会出现多次 我们如何获得数组中所有出现最大值的索引集合 例如 对于以下数组 import numpy as np a np array 1 2 3 2 3 2 1 3 结果应该是 2 4 7 或等效的数组或元组
  • Docker - 使用多模块 Maven 项目进行多阶段构建

    我有一个具有 root 的 Maven 项目pom xml具有多个子文件夹作为模块和依赖项的文件 它看起来像这样
  • 导入错误:没有名为flask.ext.script的模块

    事实上我现在无法使用任何软件包 导入错误 没有名为flask ext script的模块 https i stack imgur com dARhF png 导入错误 没有名为 Pymongo 的模块 https i stack imgur
  • php删除大括号和里面的内容检索剩余

    want to 删除大括号内的 php 字符串的特定文本 包括大括号 它应该被删除 数据串如下所示 page header this text should not be removed menu list menu list 2 this
  • 在 Vue 3 中设置全局 Axios 标头

    我正在尝试使用 Axios 访问我的后端 Django 但在设置全局标头以在标头中包含 CSRF 令牌时遇到一些问题 这是到达我的服务器 import axios from axios async function loadCards va
  • C# 执行外部程序并捕获(流式传输)输出

    我正在编写一个程序来处理一些视频文件 我正在使用 ffmpeg 可执行文件将多个文件合并到一个文件中 该命令需要几分钟才能完成 因此 我需要一种方法来 监视 输出 并在 GUI 上显示进度条 查看以下 stackoverflow 主题 如何
  • 使用动态规划对列表进行分区

    我在这里发布了一些与我一直在尝试从事的项目相关的内容 但我不断遇到设计问题并且必须从头开始设计 所以我想知道我是否可以发布我正在尝试做的事情 并且有人可以帮助我了解如何获得我想要的结果 背景 我是编程新手 正在努力学习 因此 我开展了一个我
  • Binutils LD 创建巨大文件

    我正在尝试创建尽可能小的 ELF 我创建了一个像这样的测试文件 NASM 语法 SECTION text dd 0xdeadbeef 使用此链接描述文件 SECTIONS text text 然后我检查了平面二进制文件的大小 并通过两种方式
  • 将 UDF 应用于 Spark Dataframe 中的多个列

    我有一个如下所示的数据框 id age rbc bgr dm cad appet pe ane classification 3 48 0 normal 117 0 no no poor yes yes ckd 我写了一个 UDF 来转换分
  • 终止或停止 HtmlUnit

    我使用 htmlunit 测试一些网站 我注意到 Htmlunit 卡在一些网页上 这个问题导致调用 htmlunit 的线程不会终止 请您知道有什么方法可以停止 Htmlunit 就像在真正的网络浏览器中一样 您只需单击浏览器停止按钮即可
  • 考虑到每个静态库定义导出的功能(vc++ 2008),如何将多个静态链接库合并到一个 dll 中?

    鉴于每个静态库都定义导出功能 vc 2008 如何将多个静态链接库合并到单个 dll 中 在存在单个 dll 项目和静态链接的多个子项目 在 dll 项目中 的多项目布局中 尽管被标记为 declspec export 子项目 lib 中的
  • python Tkinter 中的简单加载屏幕

    我是一个Python初学者 尤其是tkinter 我想制作一个简单的 python 脚本的 加载屏幕 并在脚本结束后关闭 但制作窗户需要mainloop函数 这意味着它将无限循环或等待用户交互 或者我认为如此 并且它将消除 加载 屏幕的想法
  • Python 将 k-means 集群与实例关联

    我已阅读文档here http scikit learn org stable modules generated sklearn cluster KMeans html以及看着this http fromdatawithlove theg
  • 在 MongoDB 中搜索多个集合

    我知道 MongoDB 的理论以及不支持联接的事实 并且我应该尽可能使用嵌入文档或非规范化 但这里是 我有多个文档 例如 用户 嵌入了 Suburbs 但也有 名字 姓氏 郊区 其中嵌入州 嵌入 School 的 Child 属于 User
  • 在maven中查找定义属性的地方

    我目前正在各种项目和 git repo 中重构大量 pom xml 有时 项目 A 中的 pom 需要项目 B 中定义的工件 其版本由属性定义
  • 如何构建自动更新的拖放层次树

    我目前正在 R 工作 需要一种可视化分层树的方法 我希望能够最初定义一棵树 其中每个节点都有一个父节点 每个父节点可以有多个子节点 我希望能够将节点拖放到不同父级下并执行一些计算 在 R 中 然后在可视化上进行更新 例如假设每个节点都有一个
  • 正则表达式“包含”另一个正则表达式

    有没有办法测试一个正则表达式是否 包含 另一个正则表达式 例如 RegEX1 a b RegEx2 a1 b RegEX1 包含 RegEX2 据我所知 这是不可能的 我错了吗 OK joel neely has shown that it
  • C++ Boost.ASIO async_read_until 慢

    我遇到了一个不寻常的问题 我有一个 C Boost ASIO Web 服务器 为了处理传入请求 我使用以下代码 boost asio async read until socket response r n r n boost bind c