Python服务器通过TCP发送截断的图像

时间:2016-10-16 15:34:58

标签: python tcp server

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

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

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

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

我已经尝试了三种不同的方式让服务器读取文件,但它们都有相同的结果。

以下是阅读和发送文件的片段:

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())

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

1 个答案:

答案 0 :(得分:3)

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

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)