python-在通过套接字发送图像时遇到问题
我是python新手,我正在尝试制作一个脚本,用于发送/流式传输我的笔记本电脑插槽的屏幕截图。如果我运行这两个脚本,它会工作,但几秒钟后(我认为这就是发生的情况:客户机信息过载),它会给我“pickle data was truncated”错误。我所遵循的教程只用于发送字符串消息和使用缓冲区,但问题是我使用的是一个经过pickle处理的python-在通过套接字发送图像时遇到问题,python,sockets,stream,buffer,screenshot,Python,Sockets,Stream,Buffer,Screenshot,我是python新手,我正在尝试制作一个脚本,用于发送/流式传输我的笔记本电脑插槽的屏幕截图。如果我运行这两个脚本,它会工作,但几秒钟后(我认为这就是发生的情况:客户机信息过载),它会给我“pickle data was truncated”错误。我所遵循的教程只用于发送字符串消息和使用缓冲区,但问题是我使用的是一个经过pickle处理的numpy数组,如果我对它进行缓冲,它会将第二个图像写入第一个图像,并给出另一个pickle数据截断错误,我不知道该怎么办 感谢您的帮助 服务器: import
numpy
数组,如果我对它进行缓冲,它会将第二个图像写入第一个图像,并给出另一个pickle数据截断错误,我不知道该怎么办
感谢您的帮助
服务器:
import numpy as np
import socket
import pickle
import time
import mss
import cv2
import sys
s = socket.socket()
shost = socket.gethostname()
host = socket.gethostbyname(shost)
port = 8080
s.bind((host,port))
s.listen(5)
print(host)
print("Waiting for any incoming connections ... ")
conn, addr = s.accept()
print(addr, "Has connected to the server")
with mss.mss() as sct: #if i want it to be a different size
monitor = {"top": 0, "left": 0, "width": 1720, "height": 720}
while True:
img = np.array(sct.grab(sct.monitors[1]))
pack = pickle.dumps(img)
conn.send(pack)
print(sys.getsizeof(pack))
客户:
import socket
import numpy as np
import cv2
import pickle
import time
s = socket.socket()
host = input(str("Please enter the host address of the sender : "))
port = 8080
s.connect((host,port))
print("Connected ... ")
while True:
pack = s.recv(4196540)
frame = pickle.loads(pack)
cv2.imshow("Screen", frame)
pack = ' '
if cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
虽然看起来很相似,但其行为方式与类似文件的对象不同。“原始”套接字编程也并没有为您做很多内务处理,这取决于您的代码来处理它
流套接字(SOCK\u stream
类型是默认打开的类型,它只是一个字节流,它本质上与您通过它的内容无关。为了使事情更复杂,正如注释中所提到的(这就是与read()
的相似性可能令人困惑的地方),它的第一个参数bufsize
没有说明您将接收多少数据,它只限制了您准备立即接收的最大数据量。它基本上说,我得到了这个大小的缓冲区,请给出您可以达到该大小的数据量
如果您知道在您的案例中,对于任何给定的图像,您将接收多少数据(而且因为它们是固定大小的屏幕截图,我想您可能很幸运),那么您需要不断重复recv()
调用,直到获得完整的图像,然后对其执行操作并继续下一个操作
这意味着您可以替换:
pack = s.recv(4196540)
比如:
item_size = 4196540
pack = b''
while len(pack) < item_size:
remains = item_size - len(pack)
bufsize = 4096 if remains > 4096 else remains
pack += s.recv(bufsize)
说:
停止客户端的接收
还有一个关于您提到的教程的注意事项。在一些琐碎的情况下,例如发送短字符串消息,虽然您不应该依赖它,但您通常会幸运地将所有预期数据都记录在一个块中。虽然看起来很相似,但其行为方式与类似文件的对象不同。“Raw”socket编程也并没有为您做很多内务处理,这取决于您的代码来处理它
流套接字(SOCK\u stream
类型是默认打开的类型,它只是一个字节流,它本质上与您通过它的内容无关。为了使事情更复杂,正如注释中所提到的(这就是与read()
的相似性可能令人困惑的地方),它的第一个参数bufsize
没有说明您将接收多少数据,它只限制了您准备立即接收的最大数据量。它基本上说,我得到了这个大小的缓冲区,请给出您可以达到该大小的数据量
如果您知道在您的案例中,对于任何给定的图像,您将接收多少数据(而且因为它们是固定大小的屏幕截图,我想您可能很幸运),那么您需要不断重复recv()
调用,直到获得完整的图像,然后对其执行操作并继续下一个操作
这意味着您可以替换:
pack = s.recv(4196540)
比如:
item_size = 4196540
pack = b''
while len(pack) < item_size:
remains = item_size - len(pack)
bufsize = 4096 if remains > 4096 else remains
pack += s.recv(bufsize)
说:
停止客户端的接收
还有一个关于您提到的教程的注意事项。在一些琐碎的情况下,例如发送短字符串消息,虽然您不应该依赖它,但您通常会幸运地在一块中接收到所有预期数据。“接收”最多返回作为参数给定的字节数,但返回的字节数可能较少,您必须从多个调用中收集数据,直到获得所有数据。@MichaelButscher抱歉,我不太明白,所以我需要多次接收还是需要将图像分为多个部分发送?“接收”必须多次调用。您还必须相应地更改其大小参数,否则您可能会收到属于下一个图像的数据。“recv”最多返回作为参数给定的字节数,但返回的字节数可能较少,您必须从多个调用中收集数据,直到获得所有数据。@MichaelButscher抱歉,我不太明白,所以我需要多次接收还是需要将图像分为多个部分发送?“接收”必须多次调用。您还必须相应地更改其大小参数,否则您可能会收到属于下一个图像的数据。