【发布时间】:2014-10-10 06:05:56
【问题描述】:
这是我在这里的第一篇文章!
我的目标是复制单向 TCP 流的有效负载并将此有效负载同时发送到多个端点。我有一个用 Python 编写的工作原型,但是我对 Python 和 Socket 编程很陌生。理想情况下,该解决方案能够在 Windows 和 *nix 环境中运行。
这个原型可以工作,但是它会为每个 Buffer 长度(当前设置为 4096 字节)创建一个新的发送 TCP 连接。这样做的主要问题是我最终会用完本地端口来发送,理想情况下我希望数据从每个传入的 TCP 流传递到一个单独的 TCP 流输出(对于每个端点)。传入的数据可能从不到 1024 字节到数百兆字节不等。
目前每 4096 个字节启动一个新的传出 TCP 流。我不确定问题出在我的线程实现中,还是我错过了其他非常明显的东西。
在我的研究中,我发现 select() 可能会有所帮助,但是我不确定它是否合适,因为我可能需要处理一些传入的数据并在将来的某些情况下响应发送客户端。
这是我到目前为止的代码(我尝试过的一些代码变体已被注释掉):
#!/usr/bin/python
#One way TCP payload duplication
import sys
import threading
from socket import *
bufsize = 4096
host= ''
# Methods:
#handles sending the data to the endpoints
def send(endpoint,port,data):
sendSocket = socket(AF_INET, SOCK_STREAM)
#sendSocket.setblocking(1)
sendSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
#sendport = sendSocket.getsockname
#print sendport
try:
sendSocket.connect((endpoint, port))
sendSocket.sendall(data)
except IOError as msg:
print "Send Failed. Error Code: " + str(msg[0]) + ' Message: ' + msg[1]
sys.exit()
#handles threading for sending data to endpoints
def forward(service, ENDPOINT_LIST, port, data):
#for each endpoint in the endpoint list start a new send thread
for endpoint in ENDPOINT_LIST:
print "Forwarding data for %s from %s:%s to %s:%s" % (service,host,port,endpoint,port)
#send(endpoint,port,data)
ethread = threading.Thread(target=send, args=(endpoint,port,data))
ethread.start()
#handles threading for incoming clients
def clientthread(conn,service,ENDPOINT_LIST,port):
while True:
#receive data form client
data = conn.recv(bufsize)
if not data:
break
cthread = threading.Thread(target=forward, args=(service, ENDPOINT_LIST, port, data))
cthread.start()
#no data? then close the connection
conn.close()
#handles listening to sockets for incoming connections
def listen(service, ENDPOINT_LIST, port):
#create the socket
listenSocket = socket(AF_INET, SOCK_STREAM)
#Allow reusing addresses - I think this is important to stop local ports getting eaten up by never-ending tcp streams that don't close
listenSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
#try to bind the socket to host and port
try:
listenSocket.bind((host, port))
#display an error message if you can't
except IOError as msg:
print "Bind Failed. Error Code: " + str(msg[0]) + ' Message: ' + msg[1]
sys.exit()
#start listening on the socket
listenSocket.listen(10)
print "Service %s on port %s is listening" %(service,port)
while True:
#wait to accept a connection
conn, addr = listenSocket.accept()
print 'Connected to ' + addr[0] + ':' + str(addr[1]) + ' on port ' + str(port)
#start new thread for each connection
lthread = threading.Thread(target=clientthread , args=(conn,service,ENDPOINT_LIST,port))
lthread.start()
#If no data close the connection
listenSocket.close()
service = "Dumb-one-way-tcp-service-name1"
ENDPOINT_LIST = ["192.168.1.100","192.168.1.200"]
port = 55551
listen(service,ENDPOINT_LIST,port)
我查看了其他库以尝试实现我的目标,包括使用:
- 扭曲的
- 异步
- Scapy
但我发现它们对于我的适度需求和编程技能水平来说相当复杂。
如果有人对我如何改进我所拥有的方法或任何其他可以实现这一目标的方法有任何建议,请告诉我!
【问题讨论】:
-
有几种更简单或更复杂的解决方案,具体取决于所需的同步类型。假设您将收到 10MB 并希望将其中继到 3 个目的地。假设 3 号目的地在接受其数据流方面很慢。您是否想快速接收所有 10MB 并立即将其发送到其他两个目的地,并将其缓冲在内存中以供第三个使用?还是可以(甚至更好)放慢整个速度,即以最慢的连接速度接收和传递 10MB?
-
@ArminRigo,我认为同步很重要。我确实想快速接受数据。如果端点具有容量,则转发的流应该以与它进来的速度相同的速度发送,但是如果一个端点比另一个端点慢(这对我来说不太可能成为问题),它会很好地缓冲有效载荷在它被发送之前。我认为在 Python 中会出现这种情况,它会在尝试将传入的有效负载发送出去时将其缓冲在 RAM 中 - 还是我需要明确告诉它在某处缓冲它?您是否认为在某处缓冲它可以帮助我解决许多传出问题?
标签: python sockets tcp python-multithreading