转载

Python Socket传输文件不完整

Introduction

嵌入式课程的实验正在加紧写,做的是树莓派小车。写完以后准备写个专辑文章。本文说明的python socket传输文件不完整问题,就是在小车(server)向PC(client)传输图像文件时产生的。记录下问题的发现和解决。

问题发现

在使用python3 socket进行传输图片时,文件不完整,源文件有28KB的大小,但是传输到PC上的数据写到文件里,不足28KB。

猜测

一开始猜测是server发送有问题:

with open('/home/pi/motion/lastsnap.jpg', 'rb')as fin:
    r = fin.read(block_size)
    while r:
        self.request.send(r)
        r = fin.read(block_size)

其实最一开始是直接 fin.read() 发送的,我以为是因为一次性发送太多了,所以改成了分块发送。但跟这个发送的数据是没有关系的。

socket传输文件不完整 中说是因为每次发送的数据包大小问题:

每次发送的数据包不要太大!最好是1024byte。我试过,如果是8192,有80%的数据丢了;如果是4096,有50%的数据丢了;如果是512,数据基本得到保证!

据此,我对client的接收代码进行了修改,将接收的块大小进行缩小:

block_size = 2048
file_size = int(s.recv(block_size))
print(file_size)
recv_data_size = 0
data = b''
with open('/home/find/ddown/test.jpg', 'wb') as fout:
    while recv_data_size < file_size:
        data = s.recv(block_size)
        fout.write(data)
        # 注意这一行
        recv_data_size += block_size
        print(recv_data_size)

测试了 block_size 从2048到512,发现的确是越小,数据接收的越多,但是直到512,仍然是不完整的。

继续searching

tcp传输大文件接受后不完整的错误 里说明了此情况,尽管我觉得作者表述很乱,没有明白他的具体意思,但是知道了错误的原因。

在 python3 官方文档 里,socket部分,recv函数的说明:

socket.recv(bufsize[, flags])

Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

里面的bufsize参数是说的每次接收的最大的长度,而不是一定接收这么长。

因此在上面的client的代码里,

# 注意这一行
recv_data_size += block_size

应该改为:

recv_data_size += len(data)

同时也可以在过程中,打印 len(data) 来检测发送中实际接收的数据量。

再来思考下为什么修改 block_size 大小也增加了文件接收的数据,因为 block_size 越小,数据接收不到这个大小的可能越小,循环的次数就越多,接收的数据也就越多了。所以符合参考1的情况,但是此处并不是因为发送大小的原因。

socket发送文件也可以先发送md5值以便校验文件完整性。

Reference

socket传输文件不完整

tcp传输大文件接受后不完整的错误

python3 官方文档
原文  http://www.findspace.name/easycoding/1811
正文到此结束
Loading...