这个场景很简单:
使用TCP / IP我有一个客户端女巫连接到我(服务器)我想转发的数据套接字发送到另一个套接字女巫我打开,我从该套接字接收的数据backwards.Just就像一个代理。
现在我有一个线程从接收连接侦听,并产生另一个2时,从客户端连接build立。 我必须使用一个在线程中进行通信的机制。
有没有更简单的女巫,我可以用作TCP / IP代理?Linux是否有套接字转发或某种机制?
谢谢
你不需要线程。 看看select()
, epoll()
或者kqueue()
来管理多个套接字而没有任何线程(如果你在Windows上,它是completion port
)。
这是一个基于选择的服务器的例子 ,这将是一个好的开始。
你可以使用iptables做端口转发 。 这不是交流的解决方案,但它是一个2线 ,具有良好的性能,并将尽可能少的调试。
从第二个环节:
iptables -A PREROUTING -t nat -i eth1 -p tcp \ --dport 80 -j DNAT --to 192.168.1.50:80 iptables -A INPUT -p tcp -m state --state NEW \ --dport 80 -i eth1 -j ACCEPT
第一行从端口80转发到端口80,在192.168.1.50上,第二行接受连接,防止iptables丢弃它。
您可以添加其他iptables标志的约束,例如-s 10.0.3.0/24
将捕获源10.0.3.0到10.0.3.255的所有地址
一个用户级解决方案使用socat
。 例如,要接受端口8080上的连接并将它们转发到192.168.1.50:9090,可以使用:
socat TCP-LISTEN:8080,fork TCP:192.168.1.50:9090
fork
选项使得socat
允许多个连接。
对于简单的套接字转发,让内核去做。 使用iptables或者其中一个前端来配置它。
如果您需要复杂的数据嗅探/修改/转发以用于真实世界的使用,请编写一个iptables模块。
如果您需要开始(复制/拆分)数据流,或者检查或修改数据,请继续阅读。
Linux 2.6.17和更高版本,glibc 2.5及更高版本,提供了一些不错的功能: splice()
和tee()
。 您可以使用这些来避免将有效载荷复制到用户空间或从用户空间复制,从而告诉内核将特定数量的字节从一个描述符传输到另一个描述符。 ( tee()
不消耗数据,允许您发送一个或多个数据副本到其他描述符。)
你可以使用你的两个线程每个连接(每个方向一个),并让每个线程根据需要读取/检查/发送数据流。 当你知道有N个传入字节转发到一个传出套接字时,使用splice()
。 如果您有多个传出套接字,则一次使用非阻塞传出套接字, tee()
小块(但对每个块使用splice()
作为最后一个传出套接字)。
你的线程可以读取一些/所有的传入数据来决定如何处理它,但是记住,在使用splice()
或者tee()
之前,你需要write()
或者send()
你已经读过的需要send()
的部分tee()
; 他们不会奇迹般地拿起已经消耗的数据。