【Python】socket传输图像

【Python】socket传输图像,第1张

客户端截屏传给服务器端


客户端

# -*- coding: utf-8 -*-

import socket, struct, pyscreenshot, gzip
from PIL import Image
from io import BytesIO

class CLIENT():

	def __init__(self):
		self.bufSize = 10240 # 每一次传输的字节流长度
	
	def Data(self, s):
		while True:
			img = pyscreenshot.grab() # 截取屏幕图像,类型:PIL.PngImagePlugin.PngImageFile
			
			imgW = img.size[0] # 图像宽度
			imgH = img.size[1] # 图像长度
			if imgW > 1920: # 图像宽度不超过1920
				zoom = 1920/imgW
			else:
				zoom = 1
			imgResize = img.resize((int(imgW*zoom), int(imgH*zoom)), Image.Resampling.LANCZOS) # 调整后的图像
			
			imgIO = BytesIO() # 创建文件对象,类型:io.BytesIO
			imgResize.save(imgIO, 'JPEG') # 以JPEG格式存储,减少数据大小
			
			imgIOZ = BytesIO() # 创建文件对象,类型:io.BytesIO
			imgIOZ.write(gzip.compress(imgIO.getvalue())) # 压缩原图并存入文件对象
			
			imgBytes = imgIOZ.getvalue() # 图像的字节流,类型:bytes
			print(len(imgBytes)) # 显示字节流长度
			
			imgSize = len(imgBytes) # 图像大小(字节流长度),类型:int
			head = struct.pack('l', imgSize) # 构造文件头信息,内容是图像大小(字节流长度),类型:bytes
			s.send(head) # 发送文件头
		
			imgIOZ.seek(0,0) # 从开头读取图片
			while True:
				imgBuf = imgIOZ.read(self.bufSize) # self.bufSize大小的图片,类型:bytes
				if not imgBuf: # 传输完成退出循环
					break
				s.send(imgBuf) # 发送self.bufSize大小的图片

	def Client(self):
		while True: # 死循环加上try语句可以不用考虑先运行服务器端
			try: # 连接不上重试
				s = socket.socket()
				s.connect(('192.168.3.126', 9099)) # 自定义服务器IP和端口
			except Exception as e:
				print('Connection error')
				print(e)
				s.close()
				continue
			
			try: # 传输数据发生错误重试
				self.Data(s) # 处理数据并传输
			except Exception as e:
				print('Data error')
				print(e)
			finally:
				s.close()

if __name__ == '__main__':
	CLIENT().Client()


服务器端

# -*- coding: utf-8 -*-

import socketserver, struct, gzip, time
from PIL import ImageFile, Image
from io import BytesIO

def Save(imgBytes):
	imgIO = BytesIO(imgBytes)
	img = Image.open(imgIO)
	img = img.convert('YCbCr') # 转换成YCbCr格式
	img.save('.\screenshot\{:.2f}.jpeg'.format(time.time()))

class DATA(socketserver.BaseRequestHandler):

	def handle(self):
		ImageFile.LOAD_TRUNCATED_IMAGES = True

		s = self.request

		while True:
			headSize = struct.calcsize('l') # 计算文件头长度
			head = s.recv(headSize) # 接收文件头

			if head:
				imgSize = struct.unpack('l', head)[0] # 获取图像长度,类型:int
				recvSize = 0 # 接收到的数据长度
				imgBytesZ = b'' # 接收到的数据

				while True:
					if imgSize - recvSize > 0: # 不断接收数据直至没有数据
						imgBuf = s.recv(SERVER().bufSize)
						recvSize += len(imgBuf)
					else:
						break

					imgBytesZ += imgBuf

				imgBytes = gzip.decompress(imgBytesZ) # 解压数据
				Save(imgBytes) # 保存图像

class SERVER():

	def __init__(self):
		self.bufSize = 10240 # 每一次接受的字节流长度

	def Server(self):
		server = socketserver.ThreadingTCPServer(('0.0.0.0', 9099), DATA) # 自定义端口
		server.serve_forever()

if __name__ == "__main__":
	SERVER().Server()

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/788520.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存