Python实时发送TCP/IP数据

5

我目前正在使用类似以下方式在我的服务器上通过TCP/IP发送数据:

for str in lst:
  data = str + "\n"
  self._conn.sendall(data)

现在假设我的列表中有以下两个字符串

1-This is statement 1 in list
2-This is statement 2 in list

我的客户收到的第二行只有一半,就像这样。
   This is statement 1 in list
   This is 

我希望能够单独发送列表中的第一行和第二行。我知道TCP/IP是这样工作的,即它会发送所有可用的数据。我想在调用self._conn.sendall(data)之后添加延迟,但我想知道我还有哪些其他选项。我无法对数据的接收者进行更改,只能对发送者进行更改。到目前为止,我唯一的选择是在每次发送后添加延迟。


1
客户端需要继续进行 recv 调用,直到获取所有内容。我不熟悉 Python,因此无法提供具体答案。 - kicken
如果您希望对每个数据包中发送的内容有完全控制权,还可以使用UDP选项。 - Aya
3个回答

5
TCP使用数据流而非单个数据包进行通信。这就像从文件中读取数据一样。发送方将数据放入其发送缓冲区中,TCP可以自行决定何时发送数据。接收应用程序接收到数据的时间取决于发送时间和(常常不可预测的)网络状况。
如果在套接字中使用TCP_NODELAY标志(例如socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)),则可以使TCP传递更加可预测。这会导致TCP一旦数据到达其缓冲区就立即发送数据。但是,到达时间仍然无法保证。这就是为什么任何基于时间的解决方案都可能会出现问题的原因。
解决方法是将数据流分成块。有几种方法可以做到这一点。以下是其中的一些方法:
  1. 使用固定长度的消息 - 如果所有消息都有固定的长度,接收方只需 recv() 正确数量的字节,处理消息,然后等待相同数量的字节。

  2. 在每个消息之前发送消息长度。如果要发送字符串“blah”,将其编码为“0004blah”或类似内容。接收方将(始终)读取前四个字节(即0004),以确定要读取的剩余字节数。然后它将读取所需数量的字节,处理消息,然后等待下一个消息。这是一种稳健且易于实现的解决方案。

  3. 使用分隔符。文本文件中的行通过换行符(\n)分隔。同样,您可以在消息之间添加特殊的分隔符字节(或多个字节)。例如,您可以定义消息总是以美元符号($)结尾。然后,接收方只需从套接字逐字节读取,直到接收到美元符号为止。当然,如果采用此方法,必须确保消息正文不包含分隔符字符。


0
TCP有一个本地缓冲区,直到它满了才会发送。您可以强制刷新本地缓冲区,以便在每个消息后发送,但是当另一方接收这些包时,它们会存储在另一个本地缓冲区中,您的分离可能会消失。TCP是一个流,请将其用作流。您必须使用分隔符,并且在接收数据包时必须手动分隔消息。如果您想要更多控制,请使用UDP数据包。

0
TCP基于流而非独立消息。因此,您需要自己解析每个消息的终点。在您的情况下,一个想法是读取直到获得换行符,然后处理该行。请注意,您可能会读取到这样的内容:
This is statement 1 in list
This is 

然后您需要检查是否有换行符,处理该行,然后使缓冲区准备好接收其余内容,就像这样:

This is 

你能给我一个例子,展示我应该怎么做吗? - James Franco
@JamesFranco:好的,只需读取最多1000个字符到缓冲区中。在换行符('\n')处拆分缓冲区。解析前N-1个块(这些是完整的行),并保留最后一个块。然后继续读取,将内容附加到缓冲区中,并重复上述步骤。 - John Zwinck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接