Boost.Asio:异步操作超时
Boost.Asio: Async operations timeout
My Program充当客户端可以连接的服务器。客户端连接后,他将每隔 ~5 秒从服务器获取更新。这是每 5 秒调用一次以将新数据发送到客户端的write
函数:
void NIUserSession::write(std::string &message_orig)
{
std::cout << "Writing message" << std::endl;
std::shared_ptr<std::string> message = std::make_shared<std::string>( message_orig );
message->append("<EOF>");
boost::system::error_code ec;
boost::asio::async_write(this->socket_, boost::asio::buffer(*message),
boost::asio::transfer_all(), boost::bind(&NIUserSession::writeHandler,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred(),
message
));
}
void NIUserSession::writeHandler(const boost::system::error_code &error, std::size_t bytes_transferred, std::shared_ptr<std::string> message)
{
std::cout << "Write Handler" << std::endl;
if(error)
{
std::cout << "Write handler error: " << error.message() << std::endl;
this->disconnect();
}
}
void NIUserSession::disconnect()
{
std::cout << "Disconnecting client, cancling all write and read operations." << std::endl;
this->socket_.lowest_layer().cancel();
delete this;
}
如果写入操作中出现错误,服务器和客户端之间的连接将关闭,并且所有异步操作都将被取消(this->socket_.lowest_layer().cancel();
)。
问题是,如果连接超时,将不会立即调用writeHandler
。相反,写入操作会"堆叠",直到第一个操作达到writeHandler
。
这应该是程序的正常输出:
Writing message
Write Handler
... Other stuff ...
... Other stuff ...
Writing message
Write Handler
如果连接超时,则会发生以下情况:
Writing message
Write Handler
Write handler error: Connection timed out
Disconnecting client, cancling all write and read operations.
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Segmentation fault
最后,分段错误上升。我认为这是因为在其他异步操作仍在进行时调用disconnect
。我以为我可以在第一次异步操作失败后直接使用 this->socket_.lowest_layer().cancel();
来避免它,但它不起作用。
如何避免分段错误?
好吧,在取消操作时不应删除this
,因为挂起的 I/O 操作的回调仍将被调用,然后访问this
会导致未定义的行为。有多种方法可以解决此问题:
- 在你真正知道以前的数据已经写入之前,不要写入数据。您可以将传递给
NIUserSession::write
的std::string
实例排队,以防未完成的写入仍处于挂起状态,然后在未完成的写入操作完成时将它们实际写入处理程序中。这样,您就不会在进行多个 I/O 操作。 - 从
std::enable_shared_from_this
继承并传递shared_from_this()
而不是this
到async_write
调用(这是 Boost 异步 TCP 日间服务器示例所做的)。这样,挂起的 I/O 操作将保留对类的引用,并且如果所有操作都完成,则将调用析构函数。
相关文章:
- 无法在 WinRT 中获取异步操作结果 (Windows::Foundation::IAsyncOperating 接口
- 异步操作的 Asio 处理程序在其同步对应项正常工作时不会调用
- 我不明白异步操作如何使HTTP服务器并发
- 提升::Asio 使用异步操作时传输的字节
- 如何编写异步操作?
- 发生哪些线程异步操作
- C 11异步操作在树上的操作
- 在 boost::asio 中启动异步操作和运行io_service的正确顺序
- 如何实现多线程异步操作
- FTP异步操作[Wininet C++]上的ERROR_IO_PENDING
- 使用带有boost::asio异步操作的自定义streambuf
- 提升 ASIO,如何取消异步操作
- 提升异步操作不起作用(对我来说)
- 在同一条链中执行异步操作
- 将异步操作的处理程序绑定到另一个类的非静态成员
- 如果一个basic_waitable_timer在仍有异步操作等待的情况下被销毁,该怎么办
- boost::asio中异步操作的处理程序要求
- 设计一个结合同步和异步操作的c++ API
- boost::asio中异步操作超时的通用方法
- Boost.Asio:异步操作超时