簡體   English   中英

套接字錯誤:“UnicodeDecodeError:‘utf-8’編解碼器無法解碼 position 中的字節 0xff 0:起始字節無效”

[英]Socket error: "UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte"

我正在嘗試實現一種使用套接字庫發送和接收文件的方法,但是當我運行代碼時,我不斷收到錯誤消息“UnicodeDecodeError:‘utf-8’編解碼器無法解碼 position 中的字節 0xff 0:無效啟動字節”。

發件人代碼:

import os, socket

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

with open("image.jpg", "rb") as file:
    file_size = os.path.getsize("send_file.txt")

    client.send("image.jpg".encode())
    client.send(str(file_size).encode())

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

    client.close()

收件人代碼:

import socket, tqdm

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

client, addr = server.accept()

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

with open(file_name, "wb") as file:
    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[-10:] == b"<DATA_END>":
            done = True
        else:
            file_bytes += data
        progress.update(1024)

    file.write(file_bytes)

    client.close()
    server.close()

您假設 sockets 在接收時遵守發送邊界。 但這不是面向 stream 的協議(如 TCP)的工作方式。 send可以在發送之前進行緩沖,或者將發送拆分為多個低級數據鏈路數據包。 recv只獲取當前可用的數據。 值得注意的是,您不會知道您是否是字符串解碼的單詞邊界。 您需要一些其他機制來決定有用的數據塊何時到達。

適用於您的情況的協議是傳遞 header,其中每個字段由換行符分隔。 文件名或大小都沒有換行符,因此很容易區分。 接收器將讀取換行符邊界直到它具有文件名和大小,然后可以讀取有效載荷的確切大小字節。

client.py

import os, socket

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

filename = "image.jpg"

with open(filename, "rb") as file:
    file_size = os.path.getsize(filename)
    # protocol <filename>\n<size>\n<data>
    client.sendall(filename.encode("utf-8"))
    client.sendall(b"\n")
    client.sendall(str(file_size).encode("utf-8"))
    client.sendall(b"\n")
    data = file.read()
    client.sendall(data)
    client.close()

服務器.py

def recv_to_newline(s):
    buf = []
    while True:
        c = s.recv(1)
        if not len(c):
            # socket closed
            return None
        if c == b"\n":
            return b"".join(buf)
        buf.append(c)

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

client, addr = server.accept()

file_name = recv_to_newline(client).decode("utf-8")
print(file_name)
file_size = int(client.recv(1024).decode())
print(file_size)

error = False
with open(file_name, "wb") as file:
    progress = tqdm.tqdm(unit="B", unit_scale=True, unit_divisor=1000, total=int(file_size))
    while file_size:
        data = client.recv(min(1024, file_size))
        if not data:
            print("Error: Truncated recieve")
            error = True
            break
        file.write(data)    
        progress.update(len(data))
        file_size -= len(data)

if error:
    os.remove(file_name)
    
client.close()
server.close()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM