Boost.Asio - 如何检查链中执行的所有中间处理程序?

时间:2016-11-22 01:56:19

标签: c++ multithreading sockets ssl boost

我有使用Boost.Asio和SSL的客户端 - 服务器应用程序。服务器有很多线程。服务器使用async_read,有时我会使用bytes_received != bytes_expectedec == 0调用异步处理程序。大多数时候应用程序错过了2048-16384字节中的1-500个字节(应用程序中通常的逻辑数据包大小)。

我的问题与此类似 - Why boost::asio::async_read completion sometimes executed with bytes_transferred=0 and ec=0?

要解决此问题,我为每个io_service::strand制作了专用ssl::stream ,为io_service::strand制作了一个ssl::context(在线程之间共享)。我用io_service::strand::wrap()(async_read,async_write,async_wait)包装了所有异步调用。常规通过io_service::strand::post()发起。我在每次调用套接字方法(io_service::strand::running_in_this_thread())之前都进行了调试检查。但是我还有破包......

由于在处理async_read / async_write Boost期间此答案https://stackoverflow.com/a/12801042/1802974,所以.Asio可以使intermediate handlers必须在链内。这是解决这个奇怪问题的最后机会。如何检查所有intermediate handlers是否在专用套接字链内实际执行?

更新

经过大量调试后我发现了我的问题 - 它根本没有连接到SSL。那是因为错误操纵缓冲区......

在我的应用程序中,我使用std::vector<char>作为缓冲区(每个套接字有两个向量 - 一个用于读取操作,一个用于写入操作)。在套接字打开后立即使用默认(零)长度创建的向量。

我有二进制协议。每个数据包由标头和有效负载组成。标头包含有效负载的长度。在服务器收到数据包的标头后,它会检查读缓冲区是否足以接收有效负载。如果缓冲区小于数据包有效负载 - 服务器会增加缓冲区。

用于管理缓冲区大小的代码(不要这样做):

if (buf.capacity() >= newSize)
{
    return;
}
buf.resize(newSize);

之后我构建了这样的asio缓冲区:

boost::asio::buffer(myVector, expectedPacketLength)

即。使用了这个重载:boost.org

现在我们将看到错误:

- Client sends packet of the length 400
- Server increases size of the buffer to 400 (size == 400, capacity == 400)
- Server successfully receives packet
- Client sends packet of the length 415
- Server increases size of the buffer to 415.
  But `std::vector` has its own logic to increase capacity and reallocate data.
  After 'resizing' actual parameters - capacity == 800, size == 415.
- Server successfully receives packet
- Client sends packet of the length 430
- Server try to increase size of a buffer, but capacity is already bigger than 430.
  Nothing is done.
- Server creates buffer.
  But mentioned overload of `boost::asio::buffer` has its own logic - size of created buffer 415.
- voila, we miss 15 last bytes of the packet

为什么我在这里发帖?

小心使用缓冲区))只需使用std::vector::reserve来增加大小并使用boost::asio::buffer boost.org的最基本重载

0 个答案:

没有答案