5

我的代码在单个线程中使用 boost::asio 和 io_service 来执行各种套接字操作。所有操作都是异步的,每个处理程序都依赖于boost::system::error_code(尤其是boost::asio::error::operation_aborted)来确定操作的结果。

在我更改逻辑以建立多个并发连接并选择最快的连接之​​前,它一直运行良好。也就是说,当第一个async_read_some处理程序触发时,我会取消其他套接字(关闭、关闭 - 一切)并继续当前的套接字。在 95% 的情况下,调用其他套接字的读取处理程序时会出现 operation_aborted 错误。但是有时,这些读取处理程序被调用而没有错误,告诉我它们已成功接收 N 个字节。

但是 socket::cancel() 的文档指出

该函数使所有未完成的异步连接、发送和接收操作立即完成,取消操作的处理程序将传递boost::asio::error::operation_aborted错误。

所以,问题是:我真的可以依赖operation_aborted生产代码中的错误吗?如果可以,它是来自 boost 1.46.1 的 Asio 中的错误吗?如果我不能,是否有任何关于此的官方文件?

4

2 回答 2

13

好的,答案:

  1. 不,我不能只依赖operation_aborted错误。
  2. 当然,这不是 Asio 的 bug,只是我这方面经验不足。
  3. 有一点官方文档。它适用于计时器,而不是套接字,但同样的原则适用:

如果在调用 cancel() 时计时器已经过期,那么异步等待操作的处理程序将:

  • 已经被调用;或者
  • 已在不久的将来排队等待调用。

基本上,我错误地假设如果我为 io_service 使用单个线程,那么在某些处理程序执行时每个操作都会被阻塞。

我报告的行为实际上很有意义,似乎每个使用 Asio 的人都知道这一点。我梳理了 Asio 的邮件列表,并在此处此处此处此处找到了很多关于该主题的讨论。

例如,当您在处理程序中但在您开始调用套接字取消之前,写入操作可能会成功完成,从而导致其完成处理程序被发布到队列中。据我了解,错误代码由已完成操作的状态确定,而不是在处理程序从队列中取出并执行时的套接字状态。

于 2012-05-30T19:21:14.420 回答
2

考虑同时建立两个连接。两个处理程序都会触发,一个将首先处理,第二个在队列中(或在不同的线程上处理)。可以想出更多这样的例子。

因此,为了实现您的要求,您需要更多的逻辑。

于 2012-05-23T11:26:25.920 回答