我想检查Boost Asio
是否真的执行异步连接。根据{{1}}基础知识中发布的the diagrams corresponding to the asynchronous calls,当Asio
向操作系统发出信号时,操作开始,因此我在执行io_service
指令后立即理解系统尝试执行该连接。
我所理解的是,如果你不打电话给async.connect
,你就会错过结果,但操作可能已经完成。所以我尝试用run
创建一个虚拟服务器,然后使用下面附带的代码。
使用调试器,我已经逐句声明,并且在nc -l -p 9000
调用run
之前我已经停止了。在服务器中,没有任何反应。关于连接没什么 - 这很明显,因为虚拟服务器没有告诉你它 - 也不是io_service
。
在调用async_write
函数后,服务器端会立即弹出相应的消息。我一直在询问run
的IRC频道,在显示我的Boost
之后,一位非常聪明的人告诉我,这可能是因为在调用strace
之前套接字尚未就绪。显然,这不会发生在Windows上。
这是否意味着在GNU / Linux操作系统下异步并非真正异步?这是否意味着网站中显示的图表与GNU / Linux环境不对应?
关于“并非真正异步”的说明:是的,它不会阻止调用,因此线程会继续运行并执行操作,但我的意思是异步启动在他们被执行后立即进行操作。
事先非常感谢你。
代码
run
我的strace
#include <iostream>
#include <string.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
void connect_handler(const boost::system::error_code& error)
{
if(error)
{
std::cout << error.message() << std::endl;
exit(EXIT_FAILURE);
}
else
{
std::cout << "Successfully connected!" << std::endl;
}
}
void write_handler(const boost::system::error_code& error)
{
if(error)
{
std::cout << error.message() << std::endl;
exit(EXIT_FAILURE);
}
else
{
std::cout << "Yes, we wrote!" << std::endl;
}
}
int main()
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::tcp::endpoint endpoint(
boost::asio::ip::address::from_string("127.0.0.1"), 9000);
socket.async_connect(endpoint, connect_handler);
std::string hello_world("Hello World!");
boost::asio::async_write(socket, boost::asio::buffer(hello_world.c_str(),
hello_world.size()), boost::bind(write_handler,
boost::asio::placeholders::error));
io_service.run();
exit(EXIT_SUCCESS);
}
答案 0 :(得分:1)
关于boost.asio的一个奇怪的事情 - 它不是唯一的,但通常不同于特定于操作系统的异步网络框架 - 是它不依赖于辅助线程。这有很多重要的后果,可以归结为:boost.asio不是为了在后台做事。相反,它是在前景中执行多个事物。
io_service::run()
是boost.asio的“中心”,使用boost.asio的单线程程序应该花费大部分时间在io_service::run()
内等待,或者执行一个名为的完成处理程序通过它。根据特定于操作系统的内部实现,在调用该函数之前,可能会或可能不会运行特定的异步操作,这就是为什么调用它基本上是您在启动初始异步请求后所做的第一件事。
将async_connect
视为“武装”您的io_service并进行异步操作。实际的异步发生在io_service::run()
期间。事实上,紧随其后async_connect
调用async_write
是一件很奇怪的事情,我觉得它有点惊讶。通常,你会在async_write
内执行(或者更确切地说,“武装”)connect_handler
,因为只有在那时你才有一个连接的套接字。