Boost asio——读写同时进行

Posted

技术标签:

【中文标题】Boost asio——读写同时进行【英文标题】:Boost asio - reading and writing at the same time 【发布时间】:2012-11-26 23:13:05 【问题描述】:

我正在尝试使用 boost:asio 实现双向通信。我正在编写将与多个客户端通信的服务器。

我希望在没有任何同步和顺序的情况下进行客户端的写入和读取 - 客户端可以随时向服务器发送命令,并且它仍然会循环接收一些数据。当然,必须保护对共享资源的访问。

实现这一目标的最佳方法是什么?有两个线程 - 一个用于阅读,一个用于编写一个不错的选择吗?接受连接并管理多个客户端怎么样?

//编辑

“无同步和顺序”是指服务器应始终将其数据流式传输给客户端,并且它可以随时响应(更改其行为)客户端请求,而不管现在发送给他们的是什么.

【问题讨论】:

您可能需要为每个客户端的每个读取和每个写入通道设置一个线程,并需要一个额外的线程来管理传入连接。 【参考方案1】:

asio 背后的一个关键思想就是您不需要多个线程来处理多个客户端会话。您的描述有点笼统,我不确定我是否理解您所说的“我希望在没有任何同步和顺序的情况下进行客户端的写入和读取”。

一个很好的起点是 asio chat server 示例。请注意,在此示例中,如何为每个连接的客户端创建类 chat_session 的实例。只要连接处于活动状态,该类的对象就会继续发布异步读取,同时它们可以将数据写入连接的客户端。与此同时,chat_server 类的对象不断接受新的传入客户端连接。

【讨论】:

你的意思是仅仅安排异步工作就足够了 - 读取和写入并继续进行? 是的,一般来说,如果您选择读取、写入或接受的异步版本,您将提供一个回调,该回调将在该操作完成时调用。回调将在与您的 io_service 关联的任何一个线程上运行。一个常见的场景是接受完成的回调在套接字上安排读取,而该读取的回调在多个套接字上安排一个或多个写入操作,但也安排下一次读取等。简而言之,这就是发生的事情在聊天服务器示例中 关于'然后继续':实际上你确实需要调用io_services run-方法。任何调用run-方法的线程都将用于运行回调,只要有工作要做(例如出色的异步读取、写入或接受)。 聊天服务器示例显示了在启动时和在 async_read 完成处理程序中调用的 async_write。换句话说,永远不会有一个 async_read 或 async_write 与另一个同时执行。 不需要多线程和不能支持多线程操作是有区别的。 async 函数接受一个 io_service,如果有多个线程作为服务的一部分运行,它确实会导致在多个线程上调用操作。然而,在较大规模的异步写入操作的情况下,这会被打破,因为它们将在套接字上交错。【参考方案2】:

在工作中,我们正在做一些概念上非常相似的事情,我注意到重型处理程序对性能的巨大影响。 code/write handler的写端工作量太大,占用工作线程的时间过长,从而危及程序流程。尤其是 RST 数据包(关闭的连接)没有被读取处理程序足够快地检测到,因为写入操作占用了它们的甜蜜时间并占用了工作线程中的大部分处理时间。目前我通过创建两个工作线程来解决这个问题,这样一行代码就不会缺乏处理时间。诚然,这远非理想,它在我冗长的待办优化列表中。

长话短说,如果您的处理程序是轻量级的,而第二个线程处理程序的其余部分,您可以摆脱使用单个线程进行读取和写入的情况。一旦您发现奇怪的同步问题,就该减轻您的网络处理程序或向工作池添加一个额外的线程了。

【讨论】:

以上是关于Boost asio——读写同时进行的主要内容,如果未能解决你的问题,请参考以下文章

boost::asio 学习

boost::asio::ip::tcp实现网络通信的小例子

C++——boost:asio的使用

boost::async 读写在一次读取和两次写入后卡住

BOOST中read_some和 boost::asio::error::eof错误

Boost Asio总结(15)class basic_stream_socket