两个TCP套接字之间的基于内核(Linux)的数据中继

nop*_*oft 6 sockets kernel tcp splice

我写的TCP中继服务器就像对等路由器(超级节点)一样工作.

最简单的情况是两个打开的套接字和它们之间的数据中继:

clientA <---> server <---> clientB

然而,服务器必须服务大约2000个这样的AB对,即.4000个插座......

userland中有两个众所周知的数据流中继实现(基于socketA.recv() - > socketB.send()socketB.recv() - > socketA.send()):

  • 使用select/poll函数(非阻塞方法)
  • 使用线程/分叉(阻塞方法)

我使用线程,所以在最坏的情况下服务器创建2*2000个线程!我不得不限制堆栈大小,它的工作原理,但它是正确的解决方案吗?

我的问题的核心:

有没有办法避免用户区中两个套接字之间的活动数据中继?

似乎有一种被动的方式.例如,我可以从每个套接字创建文件描述符,创建两个管道并使用dup2() - 与stdin/out重定向相同的方法.然后两个线程对数据中继没用,可以完成/关闭. 问题是服务器是否应该关闭套接字和管道以及如何知道管道何时损坏以记录事实?

我也发现了"套接字对",但我不确定它是否符合我的目的.

你会建议什么解决方案来卸载用户空间并限制线程数量?

一些额外的解释:

  • 服务器已定义静态路由表(例如ID_A与ID_B - 配对标识符).客户端A连接到服务器并发送ID_A.然后服务器等待客户端B.当A和B配对(两个套接字都打开)时,服务器启动数据中继.
  • 客户端是对称NAT背后的简单设备,因此N2N协议或NAT遍历技术对于它们而言过于复杂.

感谢Gerhard Rieger,我有一个提示:

我知道有两种内核空间方法可以避免在用户空间中进行读/写,recv/send:

  • 发送文件
  • 拼接

两者都有关于文件描述符类型的限制.

dup2无助于在内核中执行某些操作,AFAIK.

手册页:splice(2) splice(2) vmsplice(2) sendfile(2) tee(2)

相关链接:

nop*_*oft 6

BSD实现SO_SPLICE:

Linux是否支持类似的东西或只有自己的内核模块是解决方案?