python - 从本地服务器下载多个文件到客户端

标签 python python-2.7 networking

下面的代码让我从服务器向客户端下载三个文件,分别是tmp.bsptmp.seqtmp.dms。然而,只有第一个文件 tmp.dms 被完全下载。另一个tmp.seq填充了tmp.bsp的信息,tmp.bsp保持0KB。

客户:

import socket 

import socket 

skClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skClient.connect(("127.0.0.1",2525))

sData = "Temp"
sData2 = "Temp"
sData3 = "Temp"

while True:
    sData = skClient.recv(1024)
    fDownloadFile = open("tmp.dms","wb")

    sData2 = skClient.recv(1024)
    fDownloadFile2 = open("tmp.seq","wb")

    sData3 = skClient.recv(1024)
    fDownloadFile3 = open("tmp.bsp","wb")

    while sData:

        fDownloadFile.write(sData)
        sData = skClient.recv(1024)
        fDownloadFile.close()

        fDownloadFile2.write(sData2)
        sData2 = skClient.recv(1024)
        fDownloadFile2.close()

        fDownloadFile3.write(sData3)
        sData3 = skClient.recv(1024)
        fDownloadFile3.close()

    print "Download over"
    break

skClient.close()

n 是一个计数器,输出用于调试。 sFileName 是下载一个文件,曾经可以工作,但因为我想要三个文件,所以我只是评论了它。

服务器:

import socket

host = ''
skServer = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
skServer.bind((host,2525))
skServer.listen(10)
print "Server currently active"

while True:
    Content,Address = skServer.accept()
    print Address
    files = "C:\Users\Name_user\Desktop\Networking\Send_Receive/"
    fUploadFile = open(files+str('tmp.dms'),"rb")
    sRead = fUploadFile.read(1024)

    fUploadFile2 = open(files+str('tmp.seq'),"rb")
    sRead2 = fUploadFile2.read(1024)

    fUploadFile3 = open(files+str('tmp.bsp'),"rb")
    sRead3 = fUploadFile3.read(1024)

    while sRead:
        Content.send(sRead)
        sRead = fUploadFile.read(1024)

        Content.send(sRead2)
        sRead2 = fUploadFile2.read(1024)

#       Content.send(sRead3)   
#       sRead3 = fUploadFile3.read(1024)

    Content.close()
    print "Sending is over"
    break


skServer.close()

我正在使用的文件:
server2.py is my server
Execution

最佳答案

您的代码的主要问题是您正在发送/接收任意数量的数据。如果您的缓冲区 (1024) 小于文件大小,则客户端文件将包含较少信息,如果缓冲区较大,则文件可能包含更多信息(来自下一个文件的数据)。

您可以通过发送一个表示文件结束的值来解决这个问题。这种方法的问题是这个值不能包含在任何文件中,客户端必须扫描接收到的数据来寻找这个值。

另一种可能的解决方案是计算文件大小并将该信息发送到文件数据之前。这样,客户就会知道每个文件需要多少数据。

使用 struct.pack我们可以创建一个包含文件大小的最小四字节 header 。

def send_file(soc, path):
    with open(path, 'rb') as f:
        data = f.read()
    size = struct.pack('!I', len(data))
    soc.send(size + data)

然后客户端可以通过读取四个字节和unpack得到文件大小荷兰国际集团诠释。

def recv_file(soc, path):
    size_header = soc.recv(4)
    size = struct.unpack('!I', size_header)[0]
    data = soc.recv(size)
    with open(path, 'wb') as f:
        f.write(data)

请注意,如果文件大小大于套接字缓冲区,则使用一次调用发送/接收文件可能会引发套接字错误。在这种情况下,您必须在循环中以较小的 block 读取数据,或者使用 socket.setsockopt 增加缓冲区大小.

这是可以处理大文件的上述函数的修改版本:

import struct
import os.path

def send_file(soc, path):
    file_size = os.path.getsize(path)
    size_header = struct.pack('!Q', file_size)
    soc.send(size_header)
    with open(path, 'rb') as f:
        while True:
            data = f.read(1024)
            if not data:
                break
            soc.send(data)

def recv_file(soc, path):
    size_header = soc.recv(8)
    file_size = struct.unpack('!Q', size_header)[0]
    chunks = [1024 for i in range(file_size / 1024)]
    with open(path, 'wb') as f:
        for chunk in chunks:
            f.write(soc.recv(chunk))
        f.write(soc.recv(file_size % 1024))

我还没有彻底测试这段代码,但它应该适用于任何大小的文件。


在您的服务器中使用 send_file 函数的示例:

host = ''
skServer = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
skServer.bind((host,2525))
skServer.listen(10)
print "Server currently active"

Content,Address = skServer.accept()
print Address

files = ['tmp.bsp', 'tmp.seq', 'tmp.dms']
for file in files:
    send_file(Content, file)

Content.close()
print "Sending is over"
skServer.close()

在客户端使用recv_file:

skClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skClient.connect(("127.0.0.1",2525))

files = ['tmp.bsp', 'tmp.seq', 'tmp.dms']
for file in files:
    recv_file(skClient, file)

print "Download over"
skClient.close()

关于python - 从本地服务器下载多个文件到客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50976915/

相关文章:

python - 如果我不关闭Python SQLite中的数据库连接怎么办

python - 如何在 Python 中绘制多个时间序列

python - 针对 python 2 与 python 3 编译时,Cython 代码运行速度慢 125 倍

python-2.7 - 无法向 Kafka 发送大消息

python - pysnmp 是线程安全的吗?

python - 优雅的数据分块方式

Python:如何解决基本 "chaos theory"程序中的舍入错误?

python - 想要在spark python中将字符串值转换为 float

linux - UDP接收程序优先级?

networking - 何时在 IP header 中设置 “Don' t 片段标志?