我正在尝试编写一个通过协议(protocol) B 处理协议(protocol) A 的服务器。
协议(protocol)A是HTTP或RTSP,协议(protocol)B是一个简单的二进制数据包序列:
[packet length][...encrypted packet data...]
所以我想用这样的东西:
boost::asio::async_read_until(socket, inputBuffer, "\r\n\r\n", read_handler);
但是,代替 socket
使用一些连接到协议(protocol) B 处理程序的伪套接字。
我有一些想法:
忘掉
async_read
、async_read_until
等,为A和B写两个状态机。混合方法:
async_read_*
用于协议(protocol) B,状态机用于 A。制作内部代理服务器。
我不喜欢 (1) 和 (2) 因为
很难将 A 与 B 解耦(我希望能够禁用协议(protocol) B)。
丑。
(3) 看起来很丑 :-)
所以问题是:我该如何实现它?
最佳答案
我过去做过类似您的回答 (2) 的事情 - 使用 async_read 调用首先读取 header ,然后使用另一个 async_read 读取长度并将剩余的内容转发到手写状态机。但我不一定会向您推荐 - 因此您可能会获得协议(protocol) B 的零拷贝 IO,但是当您知道它后面总是有数据时,读取 4-8 字节 header 的 IO 调用是非常浪费的。问题是您对 2 层的网络抽象会有所不同 - 因此您提到的解耦问题确实存在。
使用固定长度的缓冲区,仅调用 async_read 然后使用 2 个嵌套状态机处理数据(就像您在答案 (1) 中基本上提出的那样)效果很好。您的每个状态机都会简单地推送一些新接收到的数据(直接来自套接字或来自较低状态机)并进行处理。这意味着 A 不会在这里耦合到 B,因为如果输入/输出数据格式匹配,您可以直接将数据从 asio 推送到 A 状态机。
与此类似的是 Netty 和 Facebook Wangle 库中使用的模式,其中您有处理程序从管道中的较低处理程序获取数据,根据该输入执行它们的操作并将它们的解码数据输出到下一个处理程序。这些处理程序可以是状态机,但根据协议(protocol)的复杂性不一定非得如此。你可以从中得到一些灵感,例如查看一些 Wangle 文档:https://github.com/facebook/wangle/blob/master/tutorial.md
如果您不想将数据从一个协议(protocol)处理程序推送到另一个协议(protocol)处理程序,而是主动读取它(最有可能以异步方式),您还可以自己设计一些接口(interface)(例如实现 async_read(... ) 方法或允许读取完整消息而不是字节的 PacketReader),通过您的代码实现它们(以及 ByteReader 也通过 asio)并在更高级别上使用它们。因此,您将从数据处理的推送方法转变为拉取方法,这有一些优点和缺点。
关于c++ - 如何使用 boost::asio 实现嵌套协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36581082/