使用 boost 套接字,我只需要一个 io_service 吗?

2024-02-17

在几个不同的线程中有多个连接..我基本上正在做一个使用 boost/asio.hpp 和那里的 tcp 东西的基类.. 现在我正在读这个:http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/tutorial/tutdaytime1.html http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/tutorial/tutdaytime1.html它说“所有使用 asio 的程序都需要至少有一个 io_service 对象”。 所以我的基类应该有一个静态 io_service (这意味着所有程序只有 1 个,并且所有不同的线程和连接将使用相同的 io_service 对象) 或者让每个连接都有自己的io_service?

谢谢前面!

更新: 好吧,基本上我想做的是一个基本客户端的类,它将有一个套接字。 对于每个套接字,我将有一个始终接收的线程和一个有时发送数据包的不同线程。 在这里查看后:www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/reference/ip__tcp/socket.html(无法创建超链接,因为我是新来的..所以每个帖子只有1个hyperling)我可以看到该套接字类并不完全是线程安全的..

所以有2个问题: 1. 根据我刚刚编写的设计,我是否需要为所有套接字提供 1 个 io_service(意味着使其成为静态类成员),还是应该为每个套接字提供一个? 2. 如何使其线程安全?我应该将它放在“线程安全环境”中,这意味着创建一个具有互斥体和不允许您同时发送和接收的内容的新套接字类,还是您有其他建议? 3.也许我应该进行异步设计? (ofc每个套接字将有一个不同的线程,但发送和接收将在同一个线程上?)

只是为了澄清:我正在做一个连接到很多服务器的 TCP 客户端。


您需要首先决定要使用哪种套接字通信方式:

  1. 同步 - 意味着所有低级操作都是阻塞的,通常您需要一个线程用于接受,然后需要线程(读取线程或 io_service)来处理每个客户端。

  2. 异步 - 意味着所有低级操作都是非阻塞的,在这里你只需要一个线程(io_service),并且你需要能够在某些事情发生时处理回调(即接受、部分写入、读取结果等) .)

方法 1 的优点是它比 2 更容易编码(??),但是我发现 2 最灵活,事实上,使用 2,默认情况下您有一个单线程应用程序(内部事件回调是在一个独立的线程到主调度线程),当然2的缺点是你的处理延迟会影响下一个读/写操作...当然你可以使用方法2创建多线程应用程序,但反之则不然(即单线程 1) - 因此灵活性......

所以,从根本上来说,这一切都取决于风格的选择......

EDIT:更新了新信息,这很长,我懒得写代码,boost 文档中有很多内容,我将简单地描述一下正在发生的事情,以便您受益......

[主线] - 声明 io_service 的实例 - 对于您要连接的每个服务器(我假设此信息在开始时可用),创建一个类(例如ServerConnection),并在此类中,使用上面相同的 io_service 实例创建一个 tcp::socket,并在构造函数本身中调用async_connect,注意:此调用是调度连接请求,而不是真正的连接操作(这要等到稍后才会发生) - 一旦所有ServerConnection对象(以及它们各自排队的 async_connects),调用run()在 io_service 实例上。现在主线程被阻塞,无法在 io_service 队列中调度事件。

[asio线程] io_service默认有一个调用预定事件的线程,你无法控制这个线程,要实现“多线程”程序,你可以增加io_service使用的线程数,但是对于当坚持使用它的那一刻,它会让你的生活变得简单......

asio 将根据计划列表中准备好的事件来调用 ServerConnection 类中的方法。您排队的第一个事件(在调用 run() 之前)是async_connect,现在 asio 会在与服务器建立连接时回调您,通常,您将实现一个handle_connect将被调用的方法(您将该方法传递给async_connect称呼)。在handle_connect,您所要做的就是安排下一个请求 - 在这种情况下,您想要读取一些数据(可能来自此套接字),因此您调用async_read_some并传入一个函数,当有数据时通知。一旦完成,主 asio 调度线程将继续调度其他准备好的事件(这可能是其他连接请求,甚至是async_read_some您添加的请求)。

假设您被调用是因为其中一个服务器套接字上有一些数据,这些数据通过您的处理程序传递给您async_read_some- 然后您可以处理这些数据,按照需要进行操作,但是这是最重要的一点 - 完成后,安排下一个async_read_some,这样 asio 将在可用时提供更多数据。非常重要的注意事项:如果您不再安排任何请求(即退出处理程序而不排队),那么 io_service 将耗尽要分派的事件,并且 run() (您在主线程中调用)将结束。

现在,至于写作,这有点棘手。如果您的所有写入都是作为读取调用(即在 asio 线程中)处理数据的一部分完成的,那么您无需担心锁定(除非您的 io_service 有多个线程),否则在您的 write 方法中,将数据附加到缓冲区,并安排async_write_some请求(使用 write_handler,当缓冲区被部分或完全写入时将被调用)。当 asio 处理此请求时,一旦数据写入,它将调用您的处理程序,并且您可以选择调用async_write_some再次,如果缓冲区中还有更多数据,或者没有数据,则不必费心安排写入。此时,我将提到一种技术,考虑双缓冲 - 我将就此保留。如果您在 io_service 之外有一个完全不同的线程并且您想要写入,则必须调用io_service::post方法并传入一个要执行的方法(在您的ServerConnection类)以及数据,io_service 将在可能的情况下调用此方法,并且在该方法中,您可以缓冲数据并可选择调用async_write_some如果当前正在写入未进行中.

现在有一件非常重要的事情你必须小心,你绝对不能安排 async_read_some or async_write_some如果有已经有一项正在进行中,也就是说,假设您打电话给async_read_some在套接字上,在 asio 调用此事件之前,您不得安排另一个事件async_read_some,否则你的缓冲区中将会有很多垃圾!

一个好的起点是您在 boost 文档中找到的 asio 聊天服务器/客户端,它显示了如何使用 async_xxx 方法。请记住这一点,所有 async_xxx 调用都会立即返回(在几十微秒内),因此没有blocking操作,这一切都是异步发生的。http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/chat/chat_client.cpp http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/chat/chat_client.cpp,就是我提到的例子。

现在,如果您发现这种机制的性能太慢并且您想要线程化,您所需要做的就是增加主 io_service 可用的线程数量,并在 ServerConnection 中的读/写方法中实现适当的锁定你就完成了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 boost 套接字,我只需要一个 io_service 吗? 的相关文章

  • 使用sqlbulkcopy之前如何创建表

    我有一个 DBF 文件 我正在尝试导入该文件 然后将其写入 SQL 表 我遇到的问题是 如果我使用 SqlBulkCopy 它需要我提前创建表 但在我的场景中这是不可能的 因为 dbf 文件不断变化 到目前为止 这是我的代码 public
  • 显示 div 内的用户名列表

    我是 jQuery 新手 在我的项目中 我创建了一个类User其中代码如下所示 static ConcurrentDictionary
  • C++0x 初始值设定项列表示例

    我想看看这个现有代码示例如何利用 C 0x 初始化列表功能 示例0 include
  • 在异步请求中使用超时回调

    我之前问过这个问题 但我将用提出的解决方案来完成这个问题 并提出另一个问题 我正在使用这个类来进行异步网络请求 http msdn microsoft com en us library system net webrequest aspx
  • 何时使用 C++ 私有继承而不是组合?

    你能给我一个具体的例子吗 什么时候使用私有继承优于组合 就我个人而言 我将使用组合而不是私有继承 但在某些情况下 使用私有继承可能是特定问题的最佳解决方案 正在阅读C faq http www parashift com c faq lit
  • 静态 OpenCV 库中未定义的引用

    我有一个使用 OpenCV 3 1 的 C 项目 并且使用共享库可以正常工作 但现在我想使用静态库 位于项目目录中的文件夹中 来编译它 因为我希望能够在未安装 OpenCV 的情况下导出它 如果需要还可以编辑和重新编译 这次我重新编译了 O
  • ASMX Web 服务,测试表单仅在本地计算机上适用于一种 WebMethod

    我有一个正在测试的 ASMX WebService 并且在大多数方法上我都可以使用测试表单进行测试 然而 我确实有一种方法 测试表上写着 The test form is only available for requests from t
  • 如何将 Visual-Studio 2010 切换到 c++11

    我是 c 编程新手 我想尝试 c 11 新功能 那么我要问的是如何切换 Visual studio 2010 才能编译 c 11 源代码 你可以参考这个表 VC10 中的 C 0x 核心语言功能 表格 http blogs msdn com
  • 多线程 - 比单线程慢

    当我使用多个线程而不是单线程运行程序时 它会变慢 不是应该更快吗 该程序应该遍历从起始目录开始的所有目录 并查找并打印所有名为 X 的文件 代码如下 while done pthread mutex lock lock if list is
  • 主构造函数不再在 VS2015 中编译

    直到今天 我可以使用主构造函数 例如 public class Test string text private string mText text 为了能够做到这一点 在以前的 Visual Studio CTP 中 我必须将其添加到 c
  • 如果我重新分配并且新大小为 0,会发生什么情况。这与释放等效吗?

    给出以下代码 int a NULL a calloc 1 sizeof a printf d n a a realloc a 0 printf d n a return 0 它返回 4078904 0 这个 realloc 相当于 free
  • 文件加密与解密问题

    我一直在尝试在 VC Express 2010 中加密和解密文件 我见过的所有教程和文档都需要两个FileStreams 来加密文件 一个用于读取未加密的版本 另一个用于加密 当我实际编写代码时 它不断抛出错误 告诉我它无法打开该文件 因为
  • 如何解决文件被另一个进程使用的问题?

    我一直在 VS NET 2010 中调试 没有任何问题 但现在无法建造 我收到错误 Unable to copy file filename to bin Debug filename The process cannot access t
  • 文本框中“结束编辑”的事件

    我正在 winform c 中使用文本框 并使用文本在数据库中进行查询 但每次文本更改时 我都需要不断查阅文本框的文本 因此 对于这些 我使用 KeyUp 但这个活动太慢了 文本框编辑完成后是否会触发任何事件 我考虑完成2个条件 控制失去焦
  • 在 lua 中加载 C++ 模块时出现“尝试索引字符串值”错误

    我正在尝试使用 lua 用 C 编写的函数 下面给出的是cpp文件 extern C include lua h include lauxlib h include lualib h static int add 5 lua State L
  • C# 模式匹配

    我对 C 有点陌生 我正在寻找一个字符串匹配模式来执行以下操作 我有一个像这样的字符串 该书将在 唐宁街 11 号接待处 并将由主要医疗保健人员参加 我需要创建一个 span 标签来使用 startIndex 和 length 突出显示一些
  • Web API 2.0 使用 pascalcase 模型接收驼峰式命名的 JSON 数据

    我正在尝试对我的 Web API 进行 PUT 调用 我在 WebApiConfig cs 中设置了以下内容 以处理以驼峰形式将数据发送回我的 Web 项目 config Formatters JsonFormatter Serialize
  • C# 和断点 - 这里有魔术师吗?

    我有这个 public static void ByLinkText string text for var i 0 i lt 50 i try Setup Driver FindElement By LinkText text Click
  • 线程安全的有限大小队列,不使用锁

    我正在尝试编写一个主题队列 但遇到死锁和其他多线程问题 我想用Interlocked CompareExchange避免lock用法 但这段代码并没有按预期工作 它只是擦除整个队列 我在这里做错了什么 public class FixedS
  • 查找和替换正则表达式问题

    感谢这里对我其他问题的所有大力帮助 我开始掌握正则表达式 但我仍然对这个一无所知 我的代码是 StreamReader reader new StreamReader fDialog FileName ToString string con

随机推荐