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