我编写复杂的TCP / IP客户端应用程序,生成大量传出的TCP连接。我尝试使用boost::asio
作为C ++中的可移植TCP / IP网络实现。
我发现了以下问题。见代码:
int main(int argc, char *argv[])
{
using namespace boost::asio;
io_service io;
thread ioThread([&io]()
{
while (true)
{
if (!io.run())
this_thread::sleep_for(seconds(1));
}
});
ioThread.detach();
ip::tcp::resolver r(io);
ip::tcp::resolver::query q("www.boost.org", "80");
atomic<bool> done(false);
r.async_resolve(q, [&done](const boost::system::error_code& error, ip::tcp::resolver::iterator iterator)
{
if (error)
wprintf(W("Error!\r\n"));
else
{
ip::tcp::resolver::iterator end;
while (iterator != end)
{
ip::tcp::endpoint endpoint = *iterator++;
std::cout << endpoint << std::endl;
}
}
done.store(true);
});
while (!done.load())
this_thread::sleep_for(seconds(1));
return 0;
}
此代码运行后台线程以执行io_service::run
方法。假设我们将有多个套接字使用此io_service
来执行异步操作。
在Windows(Visual Studio 2013 x64)上,此代码运行良好并打印端点地址。
在CentOS Linux 6上使用boost 1.60和clang 3.4.2它会挂起。
有什么想法async_resolve
为什么永远不会完成?
答案 0 :(得分:1)
我认为问题是你的线程函数没有重置boost::asio::io_service
实例。 documentation说:
[
reset()
]必须在run(),run_one(),poll()或poll_one()函数的任何第二组或更后一组调用之前调用 当由于这些函数返回先前调用这些函数时 io_service被停止或停止工作。
在你的程序中,boost::asio::io_service
实例返回,因为它没有工作,所以你不能再调用它(即在下一个循环迭代中)而不先调用reset()
。
你的程序中存在一种竞争条件,它会在某些情况下使用它而在某些情况下不起作用。如果解析器操作在第一次时间排队,run()
被调用,那么它将起作用。如果没有那么它将无法工作。这可以解释为什么它适用于一个操作系统而不适用于另一个操作系统。
与您的问题没有直接关系的另一个注意事项是,在循环中调用run()
的线程函数有点尴尬。如果您想控制run()
的持续时间,使用io_service::work
可能是更好的方法。