我正在尝试编写一些Python代码,这些代码将在两个TCP套接字之间建立一个不可见的中继。我目前的技术是设置两个线程,每个线程读取并随后在特定方向上一次写入1kb数据(即A到B的1个线程,B到A的1个线程)。
这适用于某些应用程序和协议,但它并非万无一失 - 有时特定应用程序在运行此基于Python的中继时的行为会有所不同。有些甚至崩溃。
我认为这是因为当我完成对套接字A的读取时,在那里运行的程序认为它的数据已经到达B,而实际上我 - 中间的狡猾的人 - 尚未发送它在B.未准备好接收数据的情况下(send()
阻塞了一段时间),我们现在处于A认为已成功向B发送数据的状态,但我仍然保持数据,等待send()
调用执行。我认为这是我在某些应用程序中发现的行为差异的原因,同时使用我当前的中继代码。我错过了什么,或听起来是否正确?
如果是这样,我真正的问题是:有没有解决这个问题的办法?当我们知道B准备好接收数据时,是否可以只读取套接字A?或者是否有另一种技术可以用来在[已经打开和放大]之间建立真正“隐形”的双向中继建立] TCP套接字?
答案 0 :(得分:5)
是否可以只读取 套接字A当我们知道B准备好了 接收数据?
当然:在套接字A和B上使用select.select(如果它返回说只有其中一个已准备就绪,在另一个套接字上使用它),并且只读取A并在您知道它们时写入B '两个都准备好了。 E.g:
import select
def fromAtoB(A, B):
r, w = select.select([A], [B], [])
if not r: select.select([A], [], [])
elif not w: select.select([], [B], [])
B.sendall(A.recv(4096))
答案 1 :(得分:1)
我认为这可能不是你的问题。
一般情况下,发送应用程序无法判断接收应用程序何时实际调用recv()来读取数据:发送方的send()可能已经完成,但源和放大器中的TCP实现完成了。目标操作系统将进行缓冲,流量控制,重传等。
即使你的中间没有中继,A只能“认为它的数据已经到达B”的唯一方法是收到B的回复说“是的,我得到了它。”
答案 2 :(得分:1)
也许您代理的应用程序编写得很糟糕。
例如,如果我调用recv(fd, buf, 4096, 0);
,我不承诺4096字节。系统尽最大努力提供它。
如果1k不是应用程序的recv
或send
大小的倍数,并且应用程序已损坏,则将发送到1k块的数据分组将会破坏应用程序。