问题描述
我写了 TCP中继服务器,它的工作原理类似于对等路由器(超级节点).
I wrote TCP relay server which works like peer-to-peer router (supernode).
最简单的情况是两个打开的套接字以及它们之间的数据中继:
The simplest case are two opened sockets and data relay between them:
clientA< --->服务器< ---> clientB
但是服务器必须服务大约2000个这样的A-B对,即. 4000个插座...
However the server have to serve about 2000 such A-B pairs, ie. 4000 sockets...
用户域中有两种众所周知的数据流中继实现(基于 socketA.recv()-> socketB.send()和 socketB. recv()-> socketA.send()):
There are two well known data stream relay implementations in userland (based on socketA.recv() --> socketB.send() and socketB.recv() --> socketA.send()):
- 使用 select /民意调查函数(非阻塞方法)
- 使用线程/派生(阻塞方法)
- using of select / poll functions (non-blocking method)
- using of threads / forks (blocking method)
我使用了线程,因此在最坏的情况下,服务器会创建2 * 2000个线程!我必须限制堆栈大小并且可以工作,但是正确的解决方案吗?
I used threads so in the worst case the server creates 2*2000 threads! I had to limit stack size and it works but is it right solution?
我的问题的核心:
有没有办法避免用户区中两个套接字之间的活动数据中继?
似乎有一种被动的方式.例如,我可以从每个套接字创建文件描述符,创建两个管道并使用dup2()-与stdin/out重定向相同的方法.然后,两个线程对于数据中继是无用的,可以完成/关闭.问题是服务器是否应该关闭套接字和管道,以及如何知道管道何时断开以记录事实?
It seems there is a passive way. For example I can create file descriptor from each socket, create two pipes and use dup2() - the same method like stdin/out redirecting. Then two threads are useless for data relay and can be finished/closed.The question is if the server should ever close sockets and pipes and how to know when the pipe is broken to log the fact?
我也找到了"socket pair",但是我不确定是否出于我的目的.
I've also found "socket pairs" but I am not sure about it for my purpose.
您会建议什么解决方案来减轻用户空间负担并限制线程数量?
一些其他说明:
- 服务器已定义了静态路由表(例如,ID_A和ID_B-配对标识符).客户端A连接到服务器并发送ID_A.然后服务器等待客户端B.当A和B配对(两个套接字都打开)时,服务器启动数据中继.
- 客户端是对称NAT之后的简单设备,因此N2N协议或NAT遍历技术对他们来说太复杂了.
感谢Gerhard Rieger的提示:
- 发送文件
- 拼接
两者都对文件描述符的类型有限制.
Both have restrictions regarding type of file descriptor.
dup2将无助于在AFAIK内核中做某事.
dup2 will not help to do something in kernel, AFAIK.
手册页: splice(2) splice(2) vmsplice(2) sendfile( 2) tee(2)
相关链接:
- 了解sendfile()和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()和send()的区别?
- 在两个文件描述符之间桥接
- 发送并在Linux中使用C/C ++(GCC/G ++)在套接字编程中接收文件
- http://ogris.de/howtos/splice.html
- 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:
OpenBSD implements SO_SPLICE:
- relayed asiabsdcon2013 幻灯片/纸张
- http://www.manualpages.de/OpenBSD /OpenBSD-5.0/man2/setsockopt.2.html
- http://metacpan.org/pod/BSD::Socket::Splice .
- relayd 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 described here
- TCP-Splicer described here
- L4/L7 switch
- HAProxy
这篇关于两个TCP套接字之间基于内核的(Linux)数据中继的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!