如何使用Python套接字发送zip文件?

问题描述 投票:0回答:1

这是我的服务器:

//server.py
import sys                                           
import socket                                                                                             
HOST = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'                                                    
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)                                                    
SIZE = 1024                                          
FORMAT = "utf-8"                                     
s = socket.socket()                                  
s.setsockopt(socket.SOL_SOCKET, 
socket.SO_REUSEADDR, 1)                                                   
s.bind((HOST, PORT))                                                                                      
s.listen(1)                                          
client = s.accept()
while True:                                           
 print(f"\033[33m[*] Listening as {HOST}:{PORT}\033[m")                                                    
 print(f"\033[32m[!] Client connected {client[1]}\033[m")
 client[0].send('copy trash'.encode())                
 filename = client[0].recv(SIZE).decode(FORMAT)
 print(f"[RECV] Receiving the filename.")
 file = open(filename, "w")
 client[0].send("Filename received.".encode(FORMAT))
 data = client[0].recv(SIZE).decode(FORMAT)
 print(f"[RECV] Receiving the file data.")
 file.write(data)
 client[0].send("File data received".encode(FORMAT))
s.close()

这是我的客户:

//client.py
import sys                                           
import socket                                        
import subprocess                                    
import tqdm
import shutil
                                                 
HOST = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'                                                    
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)                                                    
FORMAT = "utf-8"                                     
SIZE = 1024                                          
s = socket.socket()                                  
s.connect((HOST, PORT))                              
msg = s.recv(1024).decode()                          
print('[*] server:', msg)                            
if(msg.lower() == "copy trash"):                         
 shutil.make_archive("/root/trashcopy", 'zip', "/root/.local/share/Trash")                                 
 file = open("/root/trashcopy.zip", "r")     
 data = file.read() 
 s.send("trashcopy.zip".encode(FORMAT))           
 msg = s.recv(SIZE).decode(FORMAT)                    
 print(f"[SERVER]: {msg}")                            
 s.send(data.encode(FORMAT))                          
 msg = s.recv(SIZE).decode(FORMAT)
 print(f"[SERVER]: {msg}")

我想做什么?

我试图用回收站中的文件制作一个 zip 文件并将其发送到服务器,但是,编码存在问题,并且在这一行抛出错误:

s.send(data.encode(FORMAT))   

这是错误:

 UnicodeDecodeError: 'utf-8' codec can't decode byte 0x95 in position 124: invalid start byte

我该如何解决这个问题?例如,当它是

.txt
文件时,我可以毫无问题地发送文件。

这是一个解码问题,我尝试过除

utf-8
以外的其他格式解码,但没有成功。

python sockets zip client-server
1个回答
1
投票

您的代码存在几个问题。例如,读取 zip(二进制)文件时,应将其读取为字节,而不是字符串,然后将其作为字节发送。此外,您的服务器需要提前知道预期的文件大小,以便能够分块读取文件。您可以使用字节排序来做到这一点。下面是一个工作示例。数据接收方法的功劳归于this,该方法稍微修改为按照代码要求以块的形式读取数据。

编辑:服务器已修改为支持客户端重新连接。因此,

client = s.accept()
已移至 while 循环内部,并且客户端的连接在收到文件后关闭。

服务器.py

import sys                                           
import socket

HOST = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'                                                    
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)                                                    
SIZE = 1024                                          
BYTEORDER_LENGTH = 8
FORMAT = "utf-8"
s = socket.socket()                                  
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)                                                   
s.bind((HOST, PORT))                                                                                      
s.listen(1)                                          

while True:
    client = s.accept()                                          
    print(f"\033[33m[*] Listening as {HOST}:{PORT}\033[m")                                                    
    print(f"\033[32m[!] Client connected {client[1]}\033[m")

    print(f"Sending 'copy trash' msg")
    client[0].send('copy trash'.encode())

    print(f"[RECV] Receiving the file size")
    file_size_in_bytes = client[0].recv(BYTEORDER_LENGTH)
    file_size= int.from_bytes(file_size_in_bytes, 'big')
    print("File size received:", file_size, " bytes")
    client[0].send("File size received.".encode(FORMAT))

    print(f"[RECV] Receiving the filename.")
    filename = client[0].recv(SIZE).decode(FORMAT)
    print(f"[RECV]Filename received:", filename)
    client[0].send("Filename received.".encode(FORMAT))

    print(f"[RECV] Receiving the file data.")
    # Until we've received the expected amount of data, keep receiving
    packet = b""  # Use bytes, not str, to accumulate
    while len(packet) < file_size:
        if(file_size - len(packet)) > SIZE:  # if remaining bytes are more than the defined chunk size
            buffer = client[0].recv(SIZE)  # read SIZE bytes
        else:
            buffer = client[0].recv(file_size - len(packet))  # read remaining number of bytes

        if not buffer:
            raise Exception("Incomplete file received")
        packet += buffer
    with open(filename, 'wb') as f:
        f.write(packet)
        
    print(f"[RECV] File data received.")
    client[0].send("File data received".encode(FORMAT))
    client[0].close()
s.close()

客户端.py

import sys                                           
import socket                                        
import subprocess                                    
import shutil
import os

HOST = sys.argv[1] if len(sys.argv) > 1 else '127.0.0.1'                                                    
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)                                                    
FORMAT = "utf-8"                                     
SIZE = 1024
BYTEORDER_LENGTH = 8                                         
s = socket.socket()                                  
s.connect((HOST, PORT))  
                            
msg = s.recv(SIZE).decode()                          
print('[*] server:', msg)     

if(msg.lower() == "copy trash"):                         
    #shutil.make_archive("/root/trashcopy", 'zip', "/root/.local/share/Trash")                                 
    shutil.make_archive("_trashcopy", 'zip', "Trash")
    
    file_size = os.path.getsize('_trashcopy.zip')
    print("File Size is :", file_size, "bytes")
    file_size_in_bytes = file_size.to_bytes(BYTEORDER_LENGTH, 'big')
    
    print("Sending the file size")
    s.send(file_size_in_bytes)
    msg = s.recv(SIZE).decode(FORMAT)                    
    print(f"[SERVER]: {msg}")
    
    print("Sending the file name")
    s.send("trashcopy.zip".encode(FORMAT))           
    msg = s.recv(SIZE).decode(FORMAT)                    
    print(f"[SERVER]: {msg}")  
    
    print("Sending the file data")    
    with open ('_trashcopy.zip','rb') as f1:
        s.send(f1.read())  
    msg = s.recv(SIZE).decode(FORMAT)
    print(f"[SERVER]: {msg}")
s.close()
© www.soinside.com 2019 - 2024. All rights reserved.