【问题标题】:boost::asio: How to detect that the receiver socket is closed in async_write handler?boost::asio: 如何检测接收器套接字在 async_write 处理程序中已关闭?
【发布时间】:2019-08-03 03:11:17
【问题描述】:

实现:

客户端使用 async_write 向服务器发送消息。在写处理程序中,它开始下一个 async_write 操作。

服务器使用 async_read 从客户端接收消息。在读取处理程序中,它开始下一个 async_read 操作。

我想在远程端关闭时立即停止异步操作。

当我关闭客户端时,async_read 立即使用 boost::asio::error::eof 错误代码调用处理程序。但是当服务器关闭时,客户端继续写入。如何让它调用带有错误代码的处理程序?

【问题讨论】:

  • 你不能,因为你不能立即知道。您可以检测到它的唯一方法是进行写入,而且您几乎可以肯定只会在 后续 写入时检测到它。
  • 如果套接字关闭,那么 async_read 将立即返回错误。只要您正在轮询 async_read 并检查错误,那么您就不必担心 async_write 失败。
  • @user207421 是的,实际上是我写的。写入处理程序中的返回值表明我成功传输了整个消息并且没有收到错误。我认为消息被写入缓冲区或其他东西。 “通过写入检测它”是什么意思?
  • @Nina async_read中的错误是我想要的,但我也想让写端知道关闭事件并做一些事情(比如清除消息队列)
  • 如果套接字关闭,Asnyc_write 也将返回回调并返回错误。但通常您只需处理 async_read 回调中的错误。从那里您可以清除您的写入队列,因为您的 async_write 也将返回。

标签: c++ boost-asio


【解决方案1】:

简单来说,你的设计应该是这样的:

Call async_read

当你需要写的时候

Call async_write

在之前的 async_write 调用返回之前,不要再次调用 async_write。 如果您需要调用多个 async_write 操作,请查询您的缓冲区。

Call async_write
callback pull next buffer from que
Call async_write
callback pull next buffer from que
Call async_write
callback pull next buffer from que

通过这样做,您可以确保每个套接字始终只有一个 async_write 操作有效。应该是这样的。 不要这样做。

Call async_write
Call async_write
Call async_write
callback
callback
callback

这是您在读取操作发生错误后尝试停止 async_write 时遇到问题的地方。 当 async_read 返回错误时,您不再需要在 async_write 操作中采取额外步骤来取消并发调用。

Call async_read
Call async_write
async_read callback returns with error (do not call async_read again)
async_write returns with error (do not call async_write again)

因此,在调用 async_write 时,如果该标志为真,请检查一个标志(正在写入),然后将您的缓冲区推送到您的队列中。当回调返回时,检查你的队列,拉下一个缓冲区并再次调用 async_write。如果 iswriting 为 false,则只需调用 async_write 而不是将其推送到队列。如果您的回调返回并且您的队列最终为空,则再次将 iswriting 设置为 false。

这一切都非常简单......

【讨论】:

  • 你没有发布你的代码,所以我可以假设你调用 async_write 错误。因为它应该返回。根据 boost 的文档:“该函数用于异步写入一定字节数的数据到流中。函数调用总是立即返回。异步操作将继续进行,直到满足以下条件之一:提供的缓冲区已被写入。也就是说,传输的字节数等于缓冲区大小的总和。发生错误。"
  • 我发现读端关闭事件后提交的第一个async_write请求做的不错。指示在写句柄中传输的字节的参数是我发送的。但是下一个请求失败,错误代码为“broken pipe”。我认为这是因为在写入过程中使用了缓冲区。
【解决方案2】:

你读/写,换句话说你有一个协议,所以添加一个新标志(消息,位...),表示你将关闭套接字,并且只有在收到该消息时才关闭套接字。 当然,您的协议必须处理错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 2016-05-25
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多