我是python的新手,我正在尝试制作一个脚本,该脚本发送/传输笔记本电脑槽式插座的屏幕快照。如果我运行这两个脚本,则可以运行,但是在几秒钟后(我认为这是发生的情况:客户端的信息超载),它给我“修复数据被截断”错误。我一直遵循的教程仅用于发送字符串消息并使用缓冲区,但是问题是我正在使用已腌制的numpy
数组,如果我对其进行缓冲,它将把第二个图像写入第一个图像并给另一个泡菜数据截断的错误,我不知道该怎么办。
感谢您的任何帮助。
服务器:
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()
socket.recv()
看上去相似时,如果文件类似对象,则其行为与socket.recv()
不同。 “原始”套接字编程也不会为您做很多事情,这取决于您的代码来处理。
一个流套接字(.read()
类型,默认情况下是使用.read()
打开的那个类型)就是一个字节流,它本质上与您要通过的内容无关。要使事情变得更加复杂,例如SOCK_STREAM
在评论中提到的(这与socket.socket()
的相似之处可能令人困惑),其第一个参数socket.socket()
并未说明您将接收多少数据,它仅限制了您准备在以下时间接收的最大数据量一次,基本上是说,我得到了这种大小的缓冲区,请给我您可以达到该大小的大小。
[如果您知道针对您的情况下的任何给定图像要接收多少数据(并且由于它们固定尺寸的屏幕截图,我想您可能很幸运),那么您需要不断重复Michael Butscher通话,直到获得完整图像为止,然后对其执行操作,然后继续进行下一个。
这意味着您可以替换:
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)
个字节的数据(大概是一个腌制的图像,然后您可以继续对其进行处理。
否则,您将不得不采用其他技术:例如,您可以定义自己的协议,其中第一个recv
字节是后面的文件大小,然后您知道要为下一个项出现多少数据。或为每个项目打开新连接(另一侧已关闭的套接字上的pack
不会阻塞并产生4196540
)。
BTW最后一条注释还意味着,在发送完最后一张图像之后,服务器可以执行n
并退出(或侦听新的传入连接),并且我们可以在上面的代码段中进行另一处更改,而不是:
recv()
说:
b''
也停止在客户端接收。