我写了TCP中继服务器,它像对等路由器(超级节点)一样工作。两个TCP套接字之间的基于内核的(Linux)数据中继
最简单的情况是两个打开的套接字和数据中继它们之间:
客户端A < --->服务器< ---> clientB
但是服务器能够满足约2000 AB等对,即。 (基于socketA.recv()4000个插座...
有两种公知的在用户态数据流中继实现 - > socketB.send()和socketB.recv() - > socketA.send()):
- 使用的选择使用线程的/轮询函数(非阻塞方法)
- /叉(阻塞方法)
我用线程在最坏的情况下服务器创建2 * 2000个线程!我不得不限制堆栈大小,它的工作原理,但它是正确的解决方案?
核心我的问题:
有没有办法避免活动数据在用户态的两个插槽之间的中继?
看来有一种被动的方式。例如,我可以从每个套接字创建文件描述符,创建两个管道并使用dup2() - 与stdin/out重定向相同的方法。然后两个线程对于数据中继是无用的,并且可以完成/关闭。 问题是服务器是否应该关闭套接字和管道,以及如何知道管道何时坏掉以记录事实?
我也发现“套接字对”,但我不确定它是否适合我的目的。
你会建议什么解决方案卸载用户空间并限制线程数量?
一些额外的解释:
- 服务器定义静态路由表(例如ID_A与ID_B - 配对标识符)。客户端A连接到服务器并发送ID_A。然后服务器等待客户端B.当A和B配对(两个插座都打开)时,服务器启动数据中继。
- 客户端是对称NAT后面的简单设备,因此N2N协议或NAT穿越技术对他们来说太复杂。
感谢格哈德·丽格我有提示:
我所知道的两个内核空间的方式,以避免读/写,recv的/在 用户空间发送:
- sendfile
- 拼接
两者都有关于文件描述符类型的限制。
dup2不会帮助在内核AFAIK做些什么。
手册页: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(莱纳斯)
- 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
对于很多连接,线程数的组合,而['epoll的(4)'](http://linux.die.net/man/4/epoll)是可能是你应该看看。 –
这一点,你可以使用类似[libev(http://software.schmorp.de/pkg/libev.html) – Hasturkun
感谢。但是它仍然是用户空间中的主动中继。我相信存在一种被动的方法。服务器等待5秒超时的客户端ID,因此线程似乎是配对阶段的自然选择。 – nopsoft