4

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

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

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

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

4

3 回答 3

5

当我们知道 B 准备好接收数据时,是否可以只从套接字 A 读取?

当然:在两个套接字 A 和 B 上使用select.select(如果它返回说只有一个已准备好,请在另一个上使用它),并且只有在您知道它们都准备好时才从 A 读取并写入 B。例如:

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))
于 2010-04-09T02:43:18.077 回答
1

我不认为这可能是你的问题。

一般来说,发送应用程序无法判断接收应用程序何时真正调用 recv() 来读取数据:发送方的 send() 可能已经完成,但源和目标 OS 中的 TCP 实现将进行缓冲、流控制、重传等。

即使中间没有您的中继,A“认为其数据已经到达 B”的唯一方法是收到 B 的回复说“是的,我知道了”。

于 2010-04-09T02:40:39.953 回答
1

也许您代理的应用程序写得不好。

例如,如果我打电话recv(fd, buf, 4096, 0);,我不会得到 4096 字节的承诺。该系统尽最大努力提供它。

如果 1k 不是您的应用程序recvsend大小的倍数,并且应用程序已损坏,那么将发送的数据分组到 1k 块将损坏应用程序。

于 2010-04-09T17:12:17.980 回答