您需要先决定要使用哪种类型的套接字通信:
同步 - 意味着所有低级操作都是阻塞的,通常您需要一个线程来接受,然后是线程(读取线程或 io_service)来处理每个客户端。
异步——意味着所有的低级操作都是非阻塞的,这里你只需要一个线程(io_service),并且你需要能够在某些事情发生时处理回调(即接受,部分写入、读取结果等)
方法 1 的优点是编码 (??) 比 2 简单得多,但是我发现 2 最灵活,实际上使用 2,默认情况下您有一个单线程应用程序(内部事件回调在主调度线程的单独线程中完成),当然2的缺点是您的处理延迟会影响下一个读/写操作......当然您可以使用方法2制作多线程应用程序,但不是副反之亦然(即带有 1 的单线程)-因此具有灵活性...
所以,从根本上说,这一切都取决于风格的选择......
编辑:为新信息更新,这很长,我懒得写代码,boost docs中有很多,我将简单描述发生了什么为了您的利益...
[主线程]
- 声明一个 io_service 的实例
- 对于您要连接的每台服务器(我假设此信息在启动时可用),创建一个类(例如ServerConnection),然后在该类中,使用相同的 io_service 实例创建一个 tcp::socket从上面,在构造函数本身,调用async_connect,注意:这个调用是调度连接请求而不是真正的连接操作(这直到以后才会发生)
- 一旦所有 ServerConnection 对象(以及它们各自的 async_connects 排队),在 io_service 实例上调用 run()。现在主线程被阻塞在 io_service 队列中调度事件。
[asio thread] 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 有多个线程),否则在您的写入方法中,将数据附加到缓冲区,并安排 async_write_some 请求(使用 write_handler 将在缓冲区被部分或全部写入时调用)。当 asio 处理这个请求时,它会在数据写入后调用您的处理程序,如果缓冲区中还有更多数据或没有数据,您可以选择再次调用 async_write_some,您不必费心安排写入.在这一点上,我将提到一种技术,考虑双缓冲 - 我将保留它。如果你在 io_service 之外有一个完全不同的线程并且你想编写,你必须调用 io_service::post 方法并传入一个方法来执行(在你的 ServerConnection 类中)连同数据,io_service 将然后在可能的情况下调用此方法,然后在该方法中,您可以缓冲数据,如果当前未在进行中,则可以选择调用async_write_some。
现在有一件非常重要的事情你必须小心,你绝不能安排async_read_some 或async_write_some,如果有已经在进行中,即假设你在一个套接字上调用了async_read_some,在这个事件被asio调用之前,你不能安排另一个async_read_some,否则你的缓冲区中会有很多废话!
一个很好的起点是您在 boost 文档中找到的 asio 聊天服务器/客户端,它显示了如何使用 async_xxx 方法。请记住这一点,所有 async_xxx 调用都会立即返回(在几十微秒内),因此没有 阻塞 操作,这一切都是异步发生的。 http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/chat/chat_client.cpp,就是我所指的例子。
现在如果你发现这种机制的性能太慢并且你想要线程,你需要做的就是增加主 io_service 可用的线程数并在你的读/写中实现适当的锁定ServerConnection 中的方法,你就完成了。