Boost::asio::async_write,处理程序只调用一次
Boost::asio::async_write, handler called only once
我是boost::asio的新手,我遇到了一个问题。我正在编写一个客户端,它在循环中向服务器发送一些命令。我发送的命令带有boost::asio::async_write,我希望每次发送命令时都会调用处理程序。事实上,只有在第一次发送时,我才看到调用了该处理程序。我的客户是这样的:
Client::Client(boost::asio::io_service & p_ioService,
boost::asio::ip::tcp::endpoint p_endpoint)
: io_service(p_ioService), endpoint(p_endpoint), socket(p_ioService)
{
socket.connect(endpoint);
}
Client::~Client()
{
socket.close();
}
void Client::sendCommand(const string & p_command)
{
boost::asio::async_write(socket,boost::asio::buffer(p_command),
boost::bind(&Client::onSendingFinished,this, _1, _2));
io_service.run();
}
void Client::onSendingFinished(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
cout<<"Sent "<<bytes_transferred<<endl;
}
main.cpp中没有其他地方可以调用io_service.run。我注意到如果我打电话io_service.reset()在io_service.run()之后运行良好,每次都调用处理程序。
如果没有io_service.reset(),我应该如何解决此问题
提前感谢
我不理解调用io_service::reset()
的反感。在这种情况下,有必要在对io_service::run()
:进行任何后续调用之前进行调用
当由于
io_service
停止或耗尽工作而返回对run()
、run_one()
、poll()
或poll_one()
函数的前一次调用时,必须在对这些函数的任何第二次或以后的一组调用之前调用reset()
。
线程可能由于抛出异常而从run()
返回,但io_service
既没有停止也没有耗尽工作。在这种情况下,线程可以在不调用reset()
的情况下调用run()
。
电流Client::sendCommand()
是同步的。它启动一个异步操作,然后在io_service::run()
中阻塞,等待操作完成,这是一个实现细节。除非有多个线程调用socket
上的命令,多个线程运行io_service
,或者写操作需要是可取消的,例如从超时开始,否则用同步write()
实现Client::sendCommand()
在功能上是等效的,并且可能更容易。
void Client::sendCommand(const string & p_command)
{
boost::system::error_code ec;
std::size_t bytes_transferred =
boost::asio::write(socket, boost::asio::buffer(p_command), ec);
onSendingFinished(ec, bytes_transferred);
}
如果Client::sendCommand()
需要异步,则:
io_service
应该从Client::sendCommand()
的外部运行。如果io_service
并不总是具有未完成的工作,则当run()
返回时,可以使用io_service::work
进行控制。有关io_service::run()
何时阻止和取消阻止的更多详细信息,请参阅此答案作为缓冲区(
p_command
)提供给async_write()
的底层内存需要保持有效,直到调用了操作的处理程序Client::onSendingFinished()
。在这种情况下,可能需要在Client::sendCommand()
中制作p_command
的副本,将副本写入套接字,然后从处理程序中删除副本。[…]底层内存块的所有权由调用者保留,调用者必须保证它们在调用处理程序之前保持有效。
虽然偶尔调用reset()
本身并不坏,但有两种典型的方法可以避免这样做。
-
在第一个异步操作的处理程序中启动一个新的异步操作。CCD_ 32仅在所有处理程序完成后返回,因此在处理程序中启动的新异步操作仍然及时以保持阻塞CCD_ 33。
-
使用
io_service::work
。如果您创建了一个以io_service
为参数构造的io_service::work
实例,那么只要work
对象保持活动状态,那么对run()
的后续调用就不会返回。因此,您将不必重置任何内容。当然,这意味着,如果您希望run()
停止阻塞,那么您的一个处理程序或另一个线程必须在某个时间销毁work
对象。
仅仅发送消息是很不寻常的,双向通信更为常见。
如果你也实现了一个接收器,那么你的接收代码总是需要一个在io_service
中运行的接收处理程序,你就不会有这个问题。。。
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么 zlib 放气初始化调用一次不起作用?
- 什么是仅调用一次并调用参数的控制台应用
- 谷歌基准测试,如何只调用一次代码?
- Android JNI RegisterNatives:对所有内容调用一次,或者每个函数调用一次
- 系统调用:一次和多次,哪个更好?
- C++菱形问题 - 如何仅调用一次基方法
- 函数被多次执行,同时调用一次
- 只为NOT STATIC类的EACH对象调用一次方法
- 通过调用一次新运算符大容量分配对象
- Boost::asio::async_write,处理程序只调用一次
- 为什么析构函数被调用两次,而构造函数只被调用一次
- 强制子类实现并调用(一次)方法
- 等待中的谓词在循环中使用notify时只调用一次
- boost::future-是否保证wait_callback只被调用一次
- 为什么这个函数只被调用一次
- Qpid质子on_sendable只被调用一次
- 每次选择参数时调用一次的静态变量和函数
- 如何只执行一次方法代码,尽管每帧调用一次
- 在c++中调整vector大小时调用一次类构造函数