如何在套接字之间正确中继TCP流量?

时间:2010-04-09 02:24:22

标签: python sockets tcp portforwarding

我正在尝试编写一些Python代码,这些代码将在两个TCP套接字之间建立一个不可见的中继。我目前的技术是设置两个线程,每个线程读取并随后在特定方向上一次写入1kb数据(即A到B的1个线程,B到A的1个线程)。

这适用于某些应用程序和协议,但它并非万无一失 - 有时特定应用程序在运行此基于Python的中继时的行为会有所不同。有些甚至崩溃。

我认为这是因为当我完成对套接字A的读取时,在那里运行的程序认为它的数据已经到达B,而实际上我 - 中间的狡猾的人 - 尚未发送它在B.未准备好接收数据的情况下(send()阻塞了一段时间),我们现在处于A认为已成功向B发送数据的状态,但我仍然保持数据,等待send()调用执行。我认为这是我在某些应用程序中发现的行为差异的原因,同时使用我当前的中继代码。我错过了什么,或听起来是否正确?

如果是这样,我真正的问题是:有没有解决这个问题的办法?当我们知道B准备好接收数据时,是否可以只读取套接字A?或者是否有另一种技术可以用来在[已经打开和放大]之间建立真正“隐形”的双向中继建立] TCP套接字?

3 个答案:

答案 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不是应用程序的recvsend大小的倍数,并且应用程序已损坏,则将发送到1k块的数据分组将会破坏应用程序。