【问题标题】:Python: Why does Python TCP-client receive data so slowly on different compared to same PC?Python:为什么 Python TCP-client 在不同的 PC 上接收数据的速度比同一台 PC 慢?
【发布时间】:2019-06-23 20:08:48
【问题描述】:

我有两个 Python 脚本,一个 TCP 服务器发送数据(以每秒 1/256 次的速率)和一个 TCP 客户端接收数据。在客户端脚本中,我打印接收到的数据的长度。 我从服务器发送了字符串“5.8”(因此数据长度为 3)。

当客户端和服务器在同一台机器上时: 接收到的数据长度始终为 3。 当客户端和服务器位于同一本地网络中的不同机器上时: 数据长度不同,但在 39 左右(发送数据的 13 倍)。

对于这种差异是否有可能的解释?

我认为增加这么多延迟的网络不太可能,因为命令行“ping”最多可以打印 2 毫秒的延迟和最大的数据量。

重要提示:我使用的是 Python 2.7。

import socket

def server():
    host = 'localhost' # replace with IP address in case client is on another machine
    port = 5051

    s = socket.socket()
    s.bind((host, port))
    s.listen(1)
    client_socket, adress = s.accept()

    while True:
        client_socket.send('a'.encode())
    client_socket.close()

if __name__ == '__main__':
    server()
import socket, random, time

def client():
    host = 'localhost' # replace with IP address in case client is on another machine
    port = 5051

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s_err = s.connect_ex((host, port))
    print(s_err)

    while True:
        data = s.recv(2048)
        print(len(data)) # returns different values depending on client location
    s.close()

if __name__ == '__main__':
    client()

【问题讨论】:

  • 您服务器的数据被 TCP 中的“Nagle 算法”延迟和缓冲在连接的发送端。有关详细信息,请参阅en.wikipedia.org/wiki/Nagle%27s_algorithm,有关在 Python 中发送时抑制 Nagle 的方法,请参阅 stackoverflow.com/questions/31826762/…。不管 Nagle 是什么,即使在本地连接上发送时,正如@maxim-egorushkin 所说,TCP 总是有可能接收与发送方写入大小不同的数据块。您的程序必须准备好应对这种情况。

标签: python networking tcp


【解决方案1】:

对于这种差异是否有可能的解释?

TCP 没有消息的概念。使用多个send 调用发送的数据可以通过一个recv 调用接收,反之亦然。

TCP 是一个流,您需要自己在其中分隔消息,以便读者可以确定消息边界。最常见的方式:

  1. 固定消息长度的消息前缀。
  2. 读取直到遇到消息分隔符,例如\n

【讨论】:

【解决方案2】:

我会假设服务器的 TCP/IP 堆栈只是连接小数据包以获得更好的网络吞吐量。要仅发送 3 个有效负载数据,您将有很大的开销:TCP 封装 + IP 封装。许多 TCP/IP 堆栈都使用它。

无论如何,您不必为此担心,也不必对它发生与否感到惊讶:TCP 是一种流协议,唯一的保证是从一侧发送的所有字节将以相同的顺序到达另一侧。任何设备(发送方接收方或网络上的任何其他设备)都可以连接分段数据包。

【讨论】:

    【解决方案3】:

    这对我有用:我将 recv() 的缓冲区大小更改为我想要接收的字节数,所以在这种情况下

    data = s.recv(3)
    

    而不是

    data = s.recv(2048)
    

    在本地机器上,自动决定数据可以以最小的包发送,而在使用本地网络时情况并非如此。所以我强制发送数据的大小。

    这当然可能会导致滞后问题。所以在其他地方我需要确保定期清空剩余数据并使用大缓冲区,或者在不需要时关闭连接。不确定最后一个,因为我还是个初学者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      • 2012-10-07
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多