场景非常简单:
使用TCP / IP我有一个连接到我的客户端(服务器)我想转发套接字发送给我的数据到我打开的另一个套接字以及我从那个套接字收到的数据。就像代理一样。 / p>
现在我有1个线程,它从传入连接中侦听并在建立客户端连接时产生另外2个线程。我必须使用一种机制在线程中进行通信。
我可以用什么更简单的方式充当TCP / IP代理? Linux是否有套接字转发或某种机制?
答案 0 :(得分:12)
您可以使用iptables执行port forwarding。它不是一个c解决方案,但它是一个2-line,具有良好的性能,并且调试次数最少。
从第二个链接:
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的所有地址
答案 1 :(得分:10)
一个用户级解决方案正在使用socat
。例如,要接受端口8080上的连接并将它们转发到192.168.1.50:9090,您可以使用:
socat TCP-LISTEN:8080,fork TCP:192.168.1.50:9090
fork
选项使socat
允许多个连接。
答案 2 :(得分:3)
你不需要线程。请查看select()
,epoll()
或kqueue()
,以便在没有任何线程的情况下管理多个套接字(如果您使用的是Windows,则为completion port
)。
This is an example of a select-based server,这将是一个良好的开端。
答案 3 :(得分:1)
对于简单的套接字转发,让内核去做。使用iptables或其中一个前端来配置它。
如果您需要复杂的数据嗅探/修改/转发以供实际使用,请编写iptables模块。
如果您需要发球(复制/拆分)数据流,或检查或修改数据,请继续阅读。
Linux 2.6.17及更高版本,使用glibc 2.5及更高版本,确实提供了一些不错的功能:splice()
和tee()
。您可以使用这些来避免将有效负载复制到用户空间和从用户空间复制,告诉内核将特定数量的字节从一个描述符传输到另一个描述符。 (tee()
不使用数据,允许您将一个或多个数据副本发送到其他描述符。)
您可以使用每个连接的两个线程(每个方向一个),并让每个线程根据需要读取inspect / mangle / tee数据流。当您知道有 N 传入字节转发到一个传出套接字时,请使用splice()
。如果您有多个传出套接字,请一次使用非阻塞传出套接字,tee()
个小块(但对每个块的最后一个传出套接字使用splice()
)。
您的线程可以读取部分/全部传入数据以决定如何处理它,但请记住,您需要write()
或send()
您已阅读的部分需要发送,在使用splice()
或tee()
之前;他们并没有神奇地获取已经消耗的数据。