【发布时间】:2020-07-23 22:58:10
【问题描述】:
我检查了一个 Boost 示例并进行了很多测试,但我认为当数据包(接收到的数据)小于或大于其预期缓冲区时,async_read 不会被正确调用。
在 boost.org 上有 a server 和 a client SSL 示例。在握手完成后的客户端示例中,send_request() 被调用,然后send_request() 被发送文本的确切长度。如果send_request() 不知道数据包的长度会怎样?
这有三种情况(缓冲区长度是指boost::asio::buffer(reply_, length) 中的length 参数):
包长度等于缓冲区长度
没问题,我们收到了数据包。
数据包长度大于缓冲区长度
我们得到与数据包长度一样多的数据,剩下的将在另一轮接收。问题是我们无法通过将另一个 send_request() 放入 lambda 主体来获取数据包的其余部分。当另一个send_request() 被调用(等等)时,我们将得到的残骸:
void receive_response(std::size_t length)
{
boost::asio::async_read(
socket_,
boost::asio::buffer(reply_, length),
[this](const boost::system::error_code& error, std::size_t length)
{
if (!error)
{
std::cout << "Reply: ";
std::cout.write(reply_, length);
std::cout << "\n";
receive_response(length); <---- This one
}
...
}
);
}
数据包长度小于缓冲区长度
我稍微更改了握手 lambda,以便我可以模拟这个,就像下面的代码一样。我还更改了receive_response() 和send_request() 方法,使它们不会相互调用。我预计 async_read(receive_response())的 lambda 在两个 async_writes(send_request())填充缓冲区后被调用,但它没有。
void handshake()
{
socket_.async_handshake(
boost::asio::ssl::stream_base::client,
[this](const boost::system::error_code& error)
{
if (!error)
{
receive_response(10); // Trigger async_read for length 10
send_request(); // Send a string of length 5
send_request(); // Send a string of length 5
}
...
}
);
}
有人可能会建议使用async_read_some()。我也测试过。幸运的是,它被第一个 send_request() 调用,但第二个 send_request() 没有调用 async_read_some() lambda(我在 lambda 的主体中放置了另一个 receive_response() 以进行循环)。
void receive_response(std::size_t length)
{
socket_.async_read_some(
boost::asio::buffer(reply_, length),
[this](const boost::system::error_code& error, std::size_t length)
{
...
receive_response(length);
...
}
);
}
【问题讨论】:
-
这个问题似乎混合了
send_request()和receive_response。显然,发送者知道发送了多少数据。
标签: c++ asynchronous network-programming boost-asio