gpt4 book ai didi

c++ - Boost.Asio 设计的示例莫名其妙地阻塞

转载 作者:行者123 更新时间:2023-11-30 01:06:45 25 4
gpt4 key购买 nike

我广泛使用了 Boost.Asio,但我遇到了一个我不理解的单元测试问题。我已将问题简化为一个非常人为的示例:

#include <string>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>

#include <boost/asio.hpp>
#define BOOST_TEST_MODULE My_Module
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/test/auto_unit_test.hpp>

using namespace std::string_literals;
using namespace std::chrono_literals;

namespace BA = boost::asio;
namespace BAI = BA::ip;

BOOST_AUTO_TEST_CASE(test)
{
std::mutex m;
std::condition_variable cv;

BA::io_service servicer;
auto io_work = std::make_unique<BA::io_service::work>(servicer);

auto thread = std::thread{[&]() {
servicer.run();
}};

auto received_response = false;

auto server_buf = std::array<std::uint8_t, 4096>{};
auto server_sock = BAI::tcp::socket{servicer};
auto acceptor = BAI::tcp::acceptor{servicer,
BAI::tcp::endpoint{BAI::tcp::v4(), 20123}};
acceptor.async_accept(server_sock, [&](auto&& ec) {
if (ec) {
BOOST_TEST_MESSAGE(ec.message());
}
BOOST_REQUIRE(!ec);

BOOST_TEST_MESSAGE("Accepted connection from " << server_sock.remote_endpoint() <<
", reading...");

BA::async_read(server_sock,
BA::buffer(server_buf),
[&](auto&& ec, auto&& bytes_read){
std::unique_lock<decltype(m)> ul(m);
received_response = true;

if (ec) {
BOOST_TEST_MESSAGE(ec.message());
}
BOOST_REQUIRE(!ec);

const auto str = std::string{server_buf.begin(),
server_buf.begin() + bytes_read};
BOOST_TEST_MESSAGE("Read: " << str);

ul.unlock();
cv.notify_one();
});
});

const auto send_str = "hello"s;
auto client_sock = BAI::tcp::socket{servicer, BAI::tcp::v4()};
client_sock.async_connect(BAI::tcp::endpoint{BAI::tcp::v4(), 20123},
[&](auto&& ec) {
if (ec) {
BOOST_TEST_MESSAGE(ec.message());
}
BOOST_REQUIRE(!ec);

BOOST_TEST_MESSAGE("Connected...");
BA::async_write(client_sock,
BA::buffer(send_str),
[&](auto&& ec, auto&& bytes_written) {
if (ec) {
BOOST_TEST_MESSAGE(ec.message());
}
BOOST_REQUIRE(!ec);

BOOST_TEST_MESSAGE("Written " << bytes_written << " bytes");
});
});

std::unique_lock<decltype(m)> ul(m);
cv.wait_for(ul, 2s, [&](){ return received_response; });
BOOST_CHECK(received_response);

io_work.reset();
servicer.stop();
if (thread.joinable()) {
thread.join();
}
}

我用它编译:

g++ -std=c++17 source.cc -l boost_unit_test_framework -pthread -l boost_system -ggdb

输出是:

Accepted connection from 127.0.0.1:51688, reading...
Connected...
Written 5 bytes

然后超时。

运行调试器显示 async_read 处理程序从未被调用。在它似乎没有做任何事情的阶段暂停执行,表明主线程正在等待 condition_variable (cv) 和 io_service 线程在 epoll_wait 上。

我似乎陷入了僵局,但看不出如何。

最佳答案

这就是函数定义的工作方式,它等待缓冲区有空间的字节数(http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/reference/async_read/overload1.html)。

试试这个:http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/reference/async_read/overload2.html

您可以提供回调来决定读取是否完成,这可能包括在编写者写入消息后等待和检查另一个 channel 提供的长度(如果您确定了一种无死锁的方式来做到这一点) 或就在消息本身之前。

添加这个完成条件使其工作:

[&](auto&& ec, auto&& bytes_read){
return bytes_read < 5 ? 5 - bytes_read : 0;
},

关于c++ - Boost.Asio 设计的示例莫名其妙地阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45927173/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com