简短版:
我尝试分割可能代表任何内容的字节流(例如,TCP流),并通过多个(不可靠)链接将它们发送到我控制下的接收系统。在那里,我想将这些段重新排序为发送系统首次接收它们的顺序。有关示例,请参见第二个ascii图像。生成的隧道不需要像TCP那样可靠(UDP-ish很好),但它应该处理使用多个内部链接的事实(这不是一件容易的事)。
使用包含size
和sequence number
字段的标头可以解决所有问题,但仅限于完美的世界。如果其中一个链接出现异常并且对等体不同步(意味着,接收器将读取它认为应构成标题的字节,但不要),则需要一些重新同步的机制。关于UDP,我想主要的网络堆栈会解析完整的UDP报头并对它是否不同步进行有根据的猜测,但是在这种失败之后是否有很好的方法可以恢复正常?
更长的版本,如果需要更多详细信息/上下文,请使用
我尝试在几个不同的链接/隧道之上创建单个隧道。这些链接可能不可靠,它们的设置方式并不重要:套接字,数据,点击,你有什么。我创建的隧道并不关心。它显然关心的是,它的客户获得了良好的服务,类似于您对UDP的期望。
当前版本:
我已在单个可靠的链接上实现了这样的工具,作为第一个版本(简单地说,我将引用here的源代码移植到C ++中):
+------\ TCP /------+
tun socket <---> socket tun
+------/ \------+
client server
这是如何工作的:客户端从其tun设备读取字节并将其写入套接字。两者都可以简单地实现为对文件描述符执行Linux读写操作。服务器反向接收。这适用于全双工。值得注意的是:
下一个版本:
现在,这些端点不是使用单个流套接字,而是必须使用多个链接相互通信,例如:
+----------\ /----------+
| .-- tun1A <---> tun1B --. |
tun0A ---- tapA <---> tapB ---- tun0B
| '-- socA <---> socB --' |
+----------/ \----------+
由于没有简单的方法来判断端点是否已在其tun0接口上读取完整的TCP段,因此我计划仅将字节流中的所有内容都保留在tun设备上。我想使用三个链接中的任何一个将它发送到另一端,而不考虑原始字节流所代表的内容。这样,可以使用4个单独的包将最初表示单个TCP段的一堆字节发送到另一侧。这些包需要在接收端重新排序,这本身就没有问题:只需在我已经拥有的那个字段中添加第二个字段:sequence number
,对吗?
但是,如果底层链接不可靠(可能是这样)会怎么样?如果软件包只是在其有效负载中进行了一点交换,那么我假设,目前,接收方的网络堆栈能够处理它。但是如果标题被破坏怎么办?端点可能会知道它应该读取错误的字节数,并且两个端点不同步,没有明显的修复。
我已经考虑过使用各种各样的方法和时间来实现它,但我并没有放弃希望采用更简单,更优雅的方法(请记住,最终结果并非需要可靠)。一些协议使用可靠的带外信道(如TCP)来管理有效载荷隧道,但目标是纯粹使用链路。此外,即使Linux提供各种酷网络工具(iproute2,netfilter等),所有这些都应该用C / C ++实现(如果稍微使用那些提供了一个很好的解决方案,可以在这里做出小的让步)。
现在,我缺乏想法,我希望任何人都可以提出其他方法解决这个问题!如果需要更多信息请问,我很乐意写更多信息:)
*最初将此问题放在networkengineering.stackexchange上。
修改1
我正考虑包装每一个内部链接&#34;如上图所示,带有自己的数据报套接字包装器。这个套接字(希望)至少可以保证我收到完整的数据报,这样我就不必担心在截断消息的情况下链接中断了。它确实增加了一些开销。
答案 0 :(得分:1)
很难理解你的不同步的想法,因为网络堆栈处理这个问题。无论如何,有很多方法可以解决这个问题。
您的应用程序需要实现自己的应用程序层协议,并且为了处理在不同通道中以任何顺序出现的消息,您可以使用不同的技术: