【问题标题】:How fast are python sockets supposed to be? Why are mine running very slowly?python套接字应该有多快?为什么我的运行速度很慢?
【发布时间】:2020-05-05 09:37:47
【问题描述】:

我编写了一个通过套接字发送一些数字的小程序。我在我的电脑上运行客户端程序,在虚拟机上运行服务器程序(托管在谷歌云平台上)。我正在使用的代码:

client.py:

import socket
from time import time

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect(("xx.xxx.xxx.xxx", 5555))

for i in "1234567890":
    print(f"Sending {i} at time {time()}")
    client.sendall(i.encode())

    data = client.recv(64)
    print(f"Received {data.decode()} at time {time()}")

server.py:


import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.bind(("0.0.0.0", 5555))
s.listen(2)

print("Server listening")

conn, addr = s.accept()
print("Connected to:", addr)

while True:
    data = conn.recv(2048).decode()
    if(not data):
        print("Server closing")
        break
    conn.sendall(data.encode())

client.py 的输出显示,将数据发送到服务器,然后接收并解码的往返过程大约需要 0.2 秒。这对我来说似乎相当高,套接字不应该运行得更快吗?从this 帖子看来,java 中的 tcp 套接字可以在 2 微秒 内完成往返,这比我的 0.2 秒快很多。在套接字方面,我是新手,所以我对任何事情都不太确定。如果有人可以为我提供一些见解,或者就如何使套接字更快地运行提出建议(如果可能的话,也许是不同的模块或套接字类型?),那就太好了。

我开始使用套接字是因为我想根据某人给我的教程制作一个基本的多人游戏(他的套接字似乎运行得非常快),但是在运行这段代码之后,数据传输所需的时间客户端之间似乎会导致游戏无法玩,或者至少严重缓慢并且根本不好玩。我确实看到了一些关于使用 UDP 而不是 TCP 的信息,但是在尝试了某人的 UDP 示例后,我发现它的运行速度同样慢。

注意:

  1. 服务器代码在 linux 机器上
  2. 客户端代码在 Windows 机器上
  3. 我的网速还不错,所以我认为这不是主要问题
  4. 我尝试使用socket.TCP_NODELAY,但没有效果

只是一些别人可能会觉得有用的额外信息

【问题讨论】:

  • 你有没有试过摆脱print这里的电话?默认情况下写入标准输出很慢,cf stackoverflow.com/questions/3857052/…
  • 有几件事,首先摆脱 print 语句,这些语句会使您的代码滞后,其次考虑使用 asyncio 或 gevent,因为套接字是 IO 绑定的,应该会大大加快它们的速度

标签: python sockets tcp


【解决方案1】:

您一次发送一堆小信息,而不是将它们聚合在一起并立即发送。这迫使实现效率低下。

当传输层看到第一条数据时,它不知道第二条数据即将到来,所以它立即发送。但是当它看到第二条数据时,它现在不知道它需要发送多少数据(因为它现在看到它不应该立即发送第一个数据),所以它等着看你是否将通过设置 200 毫秒的计时器发送更多。

如果你有一堆东西需要同时发送,你需要组合成一个调用底层传输层。否则,您将迫使它变得低效,因为它永远不知道它应该何时发送以及何时应该积累数据。

【讨论】:

  • 啊,我明白了。但是如果我有一个游戏循环运行,每帧我都需要发送玩家的新位置,我将不得不发送个人信息,不是吗?有没有办法指定一些东西告诉传输层不要等待新数据?
  • 除了不做你做过的事外,你不需要做任何特别的事情。聚合所有需要同时发送的数据,一次性发送。传输层将解决剩下的问题。 (您不需要超过 4KB 左右的缓冲区。发送该大小的块就可以了。只是小块会导致问题。简单的解决方案是写入缓冲区并在缓冲区达到 8KB 或何时刷新连接到连接你现在已经完成了。)
  • 最后一件事:如果对方以至少一个字节的数据响应每个“消息”,传输层将根据此计算出来。如果你的问题是你写了一堆小消息,而对方没有连贯地解析和响应。 (如果你想了解它是如何工作的,你可以在谷歌上搜索“ACK 搭载”或“应用程序级确认”。必须将 TCP 分层协议设计为与 TCP 一起使用。)
  • 我刚刚修改了代码,使它只发送第一个数字 1。这是它发送的 only 东西,但仍然需要 200 毫秒。按照你的说法,我不发送任何其他数据,不应该只是快速发送吗?
  • @Max 是的,应该。也许你到谷歌云的实际往返时间是 200 毫秒?如果是美国到澳大利亚或类似的地方,这不会太不寻常。 (将“光纤中的光速”输入您最喜欢的搜索引擎。)
猜你喜欢
  • 2021-08-12
  • 2011-04-26
  • 2014-08-08
  • 2019-06-28
  • 2021-08-02
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 2017-12-20
相关资源
最近更新 更多