Python套接字传输图片时接收计数异常问题咨询
Python套接字传图:客户端计数与预期不符的问题分析
我尝试通过Python套接字传输图片,编写了如下服务端和客户端程序。运行python server.py test.jpg时,服务端中list(fh)返回的长度为374(即文件被拆分为374个分片),但客户端的计数器仅递增1次,和预期的374次不符,需要理清问题所在。
服务端代码(server.py)
import socket import cv2 import sys c = 0 q1 = '127.0.0.1' q2 = 10001 s = socket.socket() s.bind((q1, q2)) s.listen(5) image_path = sys.argv[1] with open(image_path, 'rb') as fh: print(fh) print(dir(fh)) l = list(fh) print(len(l)) c, addr = s.accept() if c != 0: for i in fh: c.send(i)
客户端代码(client.py)
import socket import cv2 import time s = socket.socket() q = '127.0.0.1' p = 10001 condition = True s.connect((q,p)) counter = 0 with open('recieved_image.jpg', 'wb') as fh: while condition: counter = counter+1 img = s.recv(1024) if img == b'': condition = False fh.write(img) print(counter)
问题根源
1. 文件指针已被耗尽,服务端未实际发送数据
服务端代码中,l = list(fh)会将文件对象的迭代器完全耗尽,把文件指针移动到文件末尾。后续的for i in fh循环因为文件已经读完,不会执行任何迭代,所以服务端没有向客户端发送任何数据。
当服务端程序执行完毕后,套接字会被自动关闭,客户端调用s.recv(1024)会返回空字节串b'',触发循环终止,此时计数器只完成了1次递增。
2. 对TCP套接字的流模型理解有误
即使服务端正确发送了374个分片,客户端的recv调用次数也不会和服务端的send次数一一对应。因为TCP是面向流的协议,它会把连续的字节流打包成TCP段传输,底层会进行合并或拆分,客户端一次recv可能接收多个send发送的数据,反之亦然。所以用recv的调用次数来对应服务端的分片数本身就是错误的预期。
修正方案
修复服务端的文件读取问题
移除list(fh)的操作,或者在读完文件后将指针重置到开头(用fh.seek(0)),确保后续能正常读取文件内容发送;同时改用sendall确保数据全部发送,发送完毕后主动关闭连接:
# 修正后的服务端核心代码 with open(image_path, 'rb') as fh: # 若需要查看分片数,可先读取后重置指针 # l = list(fh) # print(len(l)) # fh.seek(0) # 重置指针到文件开头 c, addr = s.accept() if c: # 按固定块大小读取发送,更高效 while True: data = fh.read(1024) if not data: break c.sendall(data) c.close() # 发送完毕关闭连接,告知客户端传输结束
客户端无需依赖计数验证传输
客户端的逻辑本身可以正常接收数据,无需用计数器对应服务端的发送次数——TCP的流特性不保证这种一一对应关系,只需在recv返回空字节串时终止循环即可。
内容的提问来源于stack exchange,提问作者d0ppL3G
相关产品推荐
相关产品推荐

