我写了 TCP中继服务器,它的工作原理类似于对等路由器(超节点)。

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

客户端A 服务器 clientB

然而,服务器必须服务大约2000个这样的A-B对,即。 4000个 socket ...

用户名中有两种众所周知的数据流中继实现(基于socketA.recv()-> socketB.send()和socketB.recv()-> socketA.send()):

  • 使用选择/轮询功能(非阻塞方法)
  • 使用线程/派生(阻塞方法)

  • 我使用了线程,因此在最坏的情况下,服务器会创建2 * 2000个线程!我必须限制堆栈大小,并且可以工作,但这是正确的解决方案吗?

    我的问题的核心:

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

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

    我也找到了“ socket 对”,但是我不确定它是否适合我的目的。

    您将建议什么解决方案来减轻用户空间负担并限制线程数量?

    一些额外的解释:
  • 服务器已定义了静态路由表(例如,具有ID_B的ID_A-配对标识符)。客户端A连接到服务器并发送ID_A。然后服务器等待客户端B。当A和B配对(两个套接字都打开)时,服务器启动数据中继。
  • 客户端是对称NAT之后的简单设备,因此N2N协议(protocol)或NAT遍历技术对他们来说太复杂了。

  • 感谢Gerhard Rieger,我得到了提示:



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

    相关链接:
  • Understanding sendfile() and splice()
  • http://blog.superpat.com/2010/06/01/zero-copy-in-linux-with-sendfile-and-splice/
  • http://yarchive.net/comp/linux/splice.html(Linus)
  • C, sendfile() and send() difference?
  • bridging between two file descriptors
  • Send and Receive a file in socket programming in Linux with C/C++ (GCC/G++)
  • http://ogris.de/howtos/splice.html
  • 最佳答案

    OpenBSD实现SO_SPLICE:

  • 中继asiabsdcon2013 slides/paper
  • http://www.manualpages.de/OpenBSD/OpenBSD-5.0/man2/setsockopt.2.html
  • http://metacpan.org/pod/BSD::Socket::Splice

  • 解决方案是Linux是否支持类似功能或仅支持自己的内核模块?
  • TCPSP
  • SP-MOD描述了here
  • TCP-Splicer描述here
  • L4/L7 switch
  • HAProxy
  • 关于sockets - 两个TCP套接字之间基于内核的(Linux)数据中继,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17590816/

    10-13 08:21