1

我正在编写一个网关服务,它侦听网络套接字并将接收到的数据包路由到单独的守护进程。我打算使用 boost asio,但我遇到了几个问题。这是我计划实现的服务器的设计:

  1. 网关将使用 boost asio 监听 TCP 连接。

  2. 网关还将使用 boost asio 侦听来自守护程序的流式 Unix 域连接。

  3. 每当 tcp 连接上有数据包时,网关会查看数据包中的协议标记,并将数据包放在服务将侦听的 unix 域连接上。

  4. 每当服务连接上有数据包时,网关就会查看客户端标签并建立相应的客户端连接。

网关中的每个描述符都是非阻塞的。

我遇到了一个特殊问题,当网关写入服务连接时,如果服务套接字已满,则有可能出现 EAGAIN 或 EWOULDBLOCK 错误。我计划通过排队缓冲区和“等待服务连接准备好写入”来解决这个问题。

如果我要使用 select 系统调用“等待服务连接准备好写入”将转换为在 writefd 列表中添加 fd 并将其传递给 select。一旦服务连接准备好写入,我会将排队的缓冲区写入连接,并将从 select 的 writefdlist 中删除服务连接。

我如何用 boost asio 做同样的事情?这样的事情可能吗?

4

3 回答 3

1

使用 boost::asio 你不需要弄乱非阻塞模式和/或返回代码,如 EAGAIN EWOULDBLOCK 等。此外,你不是“向池循环添加套接字”或类似的东西;这对你来说是隐藏的,因为它是更高级的框架。

典型的模式是

  1. 您创建 io_service 对象
  2. 您创建绑定到 io_service 的套接字
  3. 您在套接字上创建一些异步事件(async_connect、async_read、async_write 等)。
  4. 您使用 io_service::run 或类似方法运行调度。
  5. asio 将在时间到时触发您的处理程序。

查看boost::asio 页面上的示例。我认为异步回显服务器可以说明您的任务的技术。

于 2013-03-08T05:56:55.930 回答
1

如果您想采用这种方法,请使用boost::asio::null_buffers启用Reactor-Style 操作socket::non_blocking()此外,通过成员函数将 Boost.Asio 套接字设置为非阻塞。此选项将同步套接字操作设置为非阻塞。这与将本机套接字设置为非阻塞不同,因为 Boost.Asio 将本机套接字设置为非阻塞,并模拟同步操作的阻塞。

然而,如果 Proactor-Style 操作是一个选项,那么考虑使用它们,因为它允许应用程序忽略一些较低级别的细节。当使用前摄器样式操作时,Boost.Asio 将代表应用程序执行 I/O,正确处理EWOULDBLOCKEAGAINERROR_RETRY逻辑。例如,当 Boost.Asio 发生前面提到的错误之一时,它将 I/O 操作推回其内部队列,推迟重新尝试,允许尝试其他操作。

通常,有两个约束需要使用 Reactor-Style 操作而不是 Proactor-Style 操作:

  • 另一个库希望自己执行 I/O 操作。
  • 内存限制。使用 Proactor,缓冲区的生命周期必须超过读取或写入操作的持续时间,并且并发操作可能需要自己的缓冲区。Reactor 允许缓冲区的生命周期从准备好读取数据时开始,并在不再使用数据时结束。
于 2013-03-08T18:48:49.280 回答
0

如果多个线程将写入用于连接的同一个套接字对象,那么您需要使用互斥锁(如果使用 Windows,则使用临界区)来单线程代码。

至于-“当网关写入服务连接时,如果服务套接字已满,则有可能出现 EAGAIN 或 EWOULDBLOCK 错误”,我相信 ASIO 会在内部为您处理,因此您不必担心它。

于 2013-03-08T13:49:26.383 回答