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

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

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

最佳答案

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

open(filename, 'rb')

来自 open() 的 Python 文档:

The default is to use text mode, which may convert '\n' characters to a platform-specific representation on writing and back on reading. Thus, when opening a binary file, you should append 'b' to the mode value to open the file in binary mode, which will improve portability. (Appending 'b' is useful even on systems that don’t treat binary and text files differently, where it serves as documentation.)

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


此外,由于 TCP 是一种流协议(protocol),因此最好将数据成更小的片段到套接字中。这避免了将整个文件读入内存的需要,这将降低内存使用量。像这样:

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

关于Python 服务器正在通过 TCP 发送截断的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40072052/

相关文章:

python - Python 维护最好的通用函数实现是什么?

java - 为什么通过套接字传输数据后,文件中的数据丢失了?

tcp - 在win CE中监听tcp事件

bash - 具有特定名称的目录的权限被拒绝

python - 使用 feedparser 从博客中获取每个独特的项目。检查 for 循环中的列表成员身份不起作用

python - ipython笔记本中的Unicode输出

python - 为什么在UDP中的UDP流接收器中视频损坏了?

java - spring 集成 tcp 服务器关闭

javascript - 使用 Javascript 和 C# 连接服务器和客户端

python - 使用 Apache Beam python 创建谷歌云数据流模板时出现 RuntimeValueProviderError