通过套接字发送和接收字节,这取决于您的网速

2024-04-26 02:37:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我用python编写了一个使用sockets发送文件的快速程序。在

服务器:

import socket, threading

#Create a socket object.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#Bind the socket.
sock.bind( ("", 5050) )

#Start listening.
sock.listen()

#Accept client.
client, addr = sock.accept()


#Open a new file jpg file.
file = open("out.jpg", "wb")


#Receive all the bytes and write them into the file.
while True:

    received = client.recv(5)

    #Stop receiving.
    if received == b'':
        file.close()
        break

    #Write bytes into the file.
    file.write( received )

客户:

^{pr2}$

从经验中得知,发送可以发送一定数量的字节 发送它们的速度是可以的。如果你举个例子:短袜发送(20 gb)您将丢失字节,因为大多数网络连接无法在 一次。你必须一部分一部分地送他们。在

所以我的问题是:如何知道套接字.send() 可以通过互联网发送吗?如何根据我的网速来改进我的程序以尽可能快地发送文件?在


Tags: 文件the程序服务器client字节bytessocket
3条回答

只需在循环中发送这些字节,直到所有字节都被发送,这里有一个example from the docs

def mysend(self, msg):
    totalsent = 0
    while totalsent < MSGLEN:
        sent = self.sock.send(msg[totalsent:])
        if sent == 0:
            raise RuntimeError("socket connection broken")
        totalsent = totalsent + sent

在您的例子中,MSGLEN将是1024,并且由于您没有使用类,所以不需要自变量

send不能保证所有的数据都被发送(它与网络速度没有直接关系;有多种原因它可以发送比请求的少),只是它让你知道发送了多少。您可以显式地向send写入循环,直到它真正发送完毕为止。在

或者您可以使用^{}来避免麻烦。sendall基本上是{a3}中描述的包装器,但是Python为您完成了所有繁重的工作。在

如果您不在乎将整个文件拖入内存,可以使用以下命令替换整个循环结构:

sock.sendall(file.read())

如果您使用的是UNIX类操作系统上的现代Python(3.5或更高版本),您可以进行一些优化,以避免使用^{}将文件数据读入Python(这只会导致出错时出现部分{}):

^{pr2}$

如果Python在您的操作系统上不支持os.sendfile,那么这只是一个有效的循环reads和{}的循环,但是在支持它的系统上,它直接从文件复制到内核中的套接字,甚至不用Python处理文件数据(通过减少系统调用和完全消除一些内存副本,可以显著提高吞吐量速度)。在

在源和目标之间的所有步骤中都有输入/输出缓冲区。一旦缓冲区被填满,在没有空间可用之前,不会接受任何其他缓冲区。在

当您的应用程序尝试发送数据时,它将在操作系统中填充一个缓冲区,当操作系统能够将数据卸载到网络设备驱动程序(也有一个缓冲区)时,该缓冲区被清除。在

网络设备驱动程序与实际网络接口,并了解如何知道何时可以发送数据,以及如何由另一方确认接收(如果有的话)。当数据被发送时,缓冲区被清空,允许操作系统从缓冲区推送更多的数据。这反过来又为您的应用程序腾出空间将更多的数据推送到操作系统。在

还有很多其他因素会影响到这个过程(超时、最大跳数是两个,我可以马上考虑),但一般的过程是,你必须在每个步骤缓冲数据,直到它可以发送到下一个步骤。在

相关问题 更多 >