python 使用套接字加速文件传输

pkln4tw6  于 2022-12-17  发布在  Python
关注(0)|答案(2)|浏览(207)

用套接字流传输文件太慢了,差不多100kbps,我用python套接字模块做了这个代码,客户端发文件名的时候就给客户端发数据了,这个东西怎么样才能提高速度呢?
下面是服务器代码

import socket
import os

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 9999))
server.listen()

client, addr = server.accept()

msg = client.recv(1024).decode()

file = open("Server_files/"+msg, "rb")
file_size = os.path.getsize("Server_files/"+msg)

# client.send("Received_image.png".encode())
client.send(str(file_size).encode())

data = file.read()
client.sendall(data)
client.send(b"<END>")

file.close()
client.close()

下面是客户端代码

import tqdm
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 9999))

file_name = input("Enter the file name: ")

client.send(file_name.encode())

file_size = client.recv(1024).decode()
print(file_size)

file = open(file_name, "wb")

file_bytes = b""

done = False

progress = tqdm.tqdm(unit="B", unit_scale=True, unit_divisor=1000,
                     total=int(file_size))

while not done:
    data = client.recv(1024)
    if file_bytes[-5:] == b"<END>":
        done = True
    else:
        file_bytes += data
    progress.update(1024)

file.write(file_bytes)

file.close()
client.close()
k5ifujac

k5ifujac1#

与其不断地向file_bytes添加输入数据(这可能需要大量的RAM,并且还需要Python多次重新分配更大的缓冲区),不如在接收到输入数据时直接将其写入data
此外,它可能有助于增加您的块大小从1024到更大的东西,也许128*1024;这将允许系统调用在每个调用中做更多的工作。

sgtfey8w

sgtfey8w2#

这里有一个完整的解决方案(Python 3.10),它允许快速下载多个文件,它使用socket.makefile来缓冲数据,with自动关闭套接字、文件和刷新tqdm进程,并在收到数据时写入数据以提高速度。
请注意,TCP不是基于消息的协议。它以相同的顺序发送字节和接收字节,但不一定具有相同的“中断”。因此,send('filename')send('filesize')可以是recv(1024),也可以是'filenamefilesize''filenamefi''lesize'或任何其他中断。因此,定义一个协议:
服务器:
1.读取后跟“\n”的文件名。
1.如果收到0字节,则连接已关闭。
1.以字符串形式发送filesize(以10为基数,后跟“\n”)。
1.精确发送“filesize”字节的文件数据。
1.重复。
委托单位:
1.发送文件名后跟“\n”
1.读取文件大小,后跟“\n”,转换为以10为基数的整数。
1.精确读取文件数据的“filesize”字节
1.如果完成,则关闭连接,否则重复。

服务器.py

import socket
import os

BLOCK = 128 << 10 # 128KB

with socket.socket() as server:
    server.bind(('', 9999))
    server.listen()

    while True:
        client, addr = server.accept()
        try:
            with (client,
                  client.makefile('rb') as rfile,
                  client.makefile('wb') as wfile):

                while True:
                    filename = rfile.readline()
                    if not filename: break

                    fullname = os.path.join('Server_files', filename.decode().rstrip('\n'))
                    file_size = os.path.getsize(fullname)
                    wfile.write(f'{file_size}\n'.encode())
                    print(f'Sending {fullname}...')
                    with open(fullname, 'rb') as file:
                        while data := file.read(BLOCK):
                            wfile.write(data)
                    wfile.flush() # make sure anything remaining in makefile buffer is sent.
                    print(f' Complete ({file_size} bytes).')
        except ConnectionResetError:
            print('Client aborted.')

客户端.py

import socket
import tqdm

BLOCK = 1 << 20  # 1MB

with socket.socket() as client:
    client.connect(('localhost', 9999))

    with (client.makefile('rb') as rfile,
          client.makefile('wb') as wfile):

        while True:
            file_name = input('File name (just ENTER to quit): ')
            if not file_name: break
            wfile.write(f'{file_name}\n'.encode())
            wfile.flush() # make sure makefile buffer is fully sent
            file_size = int(rfile.readline().decode())

            with (tqdm.tqdm(unit='B',
                            unit_scale=True,
                            unit_divisor=1000,
                            total=file_size) as progress,
                  open(file_name, 'wb') as file):

                remaining = file_size
                while remaining:
                    data = rfile.read(BLOCK if remaining > BLOCK else remaining)
                    file.write(data)
                    progress.update(len(data))
                    remaining -= len(data)

输出示例(注意下载速度):

File name (just ENTER to quit): bigfile1
100%|██████████████████████████████████████████████████████████| 191M/191M [00:00<00:00, 706MB/s]
File name (just ENTER to quit): bigfile2
100%|██████████████████████████████████████████████████████████| 218M/218M [00:00<00:00, 718MB/s]
File name (just ENTER to quit):

相关问题