【问题标题】:Python server is sending truncated images over TCPPython 服务器正在通过 TCP 发送截断的图像
【发布时间】:2017-02-25 14:11:13
【问题描述】:

我的 Windows PC 上有一个用 python 编写的简单服务器,它从目录中读取文件,然后通过 TCP 将文件发送到客户端。

客户端正确接收 HTML 和 Javascript 等文件(发送和原始文件匹配)。
问题是图像数据被截断

奇怪的是,不同的图像以不同的长度被截断,但每张图像都是一致的。
例如,一个特定的 1MB JPG 总是以 95 个字节接收。另一个应该是 7KB 的图像被接收为 120 字节。

在notepad++中打开截断的图像文件,的数据是正确的。 (唯一的问题是文件结束得太快了)。
我没有看到文件结束位置的模式。每个图像的截断前后的字符/字节不同。

我尝试了三种不同的方式让服务器读取文件,但它们的结果都是一样的。

这里是文件读取和发送的sn-p:

print ("Cache size=" + str(os.stat(filename).st_size))

#1st attempt, using readlines
fileobj = open(filename, "r") 
cacheBuffer = fileobj.readlines() 
for i in range(0, len(cacheBuffer)):
    tcpCliSock.send(cacheBuffer[i])

#2nd attempt, using line, same result
with open(filename) as f:
    for line in f:
        tcpCliSock.send(f)

#3rd attempt, using f.read(), same result
with open(filename) as f:
    tcpCliSock.send(f.read())

脚本将读取的文件大小打印到控制台,字节数与原始图像匹配。所以这证明问题出在发送上,对吧?
如果问题在于发送,我可以更改什么以正确发送整个图像?

【问题讨论】:

    标签: python tcp server


    【解决方案1】:

    由于您处理的是二进制文件,因此您需要以 binary 模式打开文件。

    open(filename, 'rb')
    

    来自open() 的 Python 文档:

    默认是使用文本模式,它可以在写入时将'\n' 字符转换为特定于平台的表示形式,并在读取时返回。因此,在打开二进制文件时,应在模式值后附加'b',以二进制模式打开文件,这将提高可移植性。 (附加 'b' 即使在不区别对待二进制文件和文本文件的系统上也很有用,它用作文档。)

    由于您的服务器在 Windows 上运行,当您 read 文件时,Python 会将它看到的每个 \r\n 转换为 \n。对于文本文件,这很好:您可以编写仅处理\n 字符的平台无关代码。对于二进制文件,这会完全破坏您的数据。这就是为什么在处理二进制文件时使用'b' 很重要,但在处理文本文件时不要使用它也很重要。


    另外,由于 TCP 是一种流协议,最好将数据以较小的片段形式进入套接字。这避免了将整个文件读入内存的需要,这将降低内存使用率。像这样:

    with open(filename, 'rb') as f:
        while True:
            data = f.read(4096)
            if len(data) == 0:
                break
            tcpCliSock.send(data)
    

    【讨论】:

    • 有理由不总是使用二进制模式吗?这会对任何文本造成问题吗?
    猜你喜欢
    • 2013-03-27
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多