• cpprestsdk有bug.


    好不容易将cpprestsdk移植到MinGW,并编译通过,出于安全还是先将samples还有tests测试一下是否正常。

    用samples/blackjack一测试就出现奇葩现象,server一端会时不时出现一次response中,两次发送headers,并且没有任何征兆。

    当用gdb调试,break+command,断点打印浏览时,却从没有发生过一次奇怪现象。毕竟断点使得程序更加慢而且更加偏向串行的方式在运行。

    下面是现象的抓包

     

     

    正常发两次包,第一次72字节header,第二次222字节content。

     异常也发了两次包,第一次72字节headers,第二次294 (72 + 222 )字节 headers + contents。

     分析代码cpprestsdk/Release/src/http/http_server_asio.cpp,发送是由m_write,m_write_size两成员控制。

    但搜索下来,只有一处赋值,“m_write = m_write_size = 0; ”,只能唯有用watch+command来观察。

    观察点分别是 14: m_write_size, 15: m_write。

     m_write_size 被修改触发断点。

     然后序列化headers,并发送。

     m_write 被修改触发断点。

     发现 m_write_size 在http_headers.match()匹配content_length字段同时赋值,无语。m_write赋值的地方也无语,分析代码根本就不能搜索到。

    从代码分析得到流程。

    1. http_response的组成,http_headers一个字典容器,body是一个instream,还有一个用于发送的streambuf。

    2. 我们的处理代码先向body写入内容,然后调用reply。

    3. http_headers先序列化到streambuf,并发送第一个数据包。

    4. 完成后将body写入streambuf,并发送第二个数据包。

    正常跟异常两种情况下,第一次发包正常,第二次发包有差。原因可能是streambuf,没有清数据。

     

     asio在取出iocp事件后,是先清streambuf数据,然后才会去回调handler,但为什么还要有例外不正常的情况发生呢。原因是cpprestsdk开发小组的成员在偷懒了。(小组压根就不打算移植到mingw,http_server的asio实现版只针对非windows,windows开发环境下默认使用httpsys实现版,所以就不会去考虑asio可能运行在winiocp的情况了)。

     没有去理会bytes_transferred,直接忽略, 回调lambda [=](error_code& ec, size_t)。但是winiocp有一种情况,就是WriteEx时马上成功了,没有发生BLOCKING。投递出去的iocp overlapped,将会是没有错误,同时bytes_transferred也为0。这样一来,asio就只会consume(0),根本没有清理数据,数据残留了下来,后续的发送就是乱套的。这种情况下,就必须自己去做处理。

     2020/06/17补充说明:

    将boost从1.54换成1.66后,async_write的handler再也没有出现error_code跟bytes_transferred同时都为0的情况。这可能是旧版boost实现的问题?

  • 相关阅读:
    .net 命名规范
    解决Swagger刷新后不能保持登录问题
    修改表结构后视图错位问题
    创建.net api文档
    编写.net core tools教程
    VuePress 侧边栏几种配置
    VS 好用快捷键
    Jenkins 修改端口
    获取当前被调用的方法
    遇到异常 add-migration Build failed 解决办法
  • 原文地址:https://www.cnblogs.com/bbqzsl/p/13127265.html
Copyright © 2020-2023  润新知