首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python -通过套接字发送图像槽时出现问题

python -通过套接字发送图像槽时出现问题
EN

Stack Overflow用户
提问于 2020-03-08 21:24:35
回答 1查看 86关注 0票数 1

我是python的新手,我正在尝试编写一个脚本来发送/流式传输我的笔记本电脑插槽的屏幕截图。如果我运行这两个脚本,它可以工作,但在几秒钟后(我认为这就是发生的情况:客户端信息过载),它会给我"pickle data was truncated“错误。我一直遵循的教程只是为了发送字符串消息和使用缓冲区,但问题是我使用的numpy数组是pickle的,如果我缓冲它,它会将第二个图像写入第一个图像,并给出另一个pickle数据截断错误,我不知道该怎么办。

任何帮助都是非常感谢的。

服务器:

代码语言:javascript
复制
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))

客户端:

代码语言:javascript
复制
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()
EN

回答 1

Stack Overflow用户

发布于 2020-03-10 05:01:59

如果文件类似于对象,则看起来类似的socket.recv().read()的行为方式不同。“原始”套接字编程也不会为您做很多内务工作,它取决于您的代码来处理它。

流套接字(默认情况下使用socket.socket()打开的SOCK_STREAM类型)就是一个字节流,它本质上与您传递的内容无关。让事情变得更复杂的是,正如Michael Butscher在评论中提到的(这也是与read()相似之处可能令人困惑的地方),它的第一个参数bufsize没有说明您将收到多少数据,它只限制了您准备立即接收的最大数量。它基本上是说,我有这个大小的缓冲区,给我你能达到的大小。

如果你知道在你的例子中任何给定的图像你要接收多少数据(因为它们是固定大小的屏幕截图,我猜你可能很幸运),你需要不断重复recv()调用,直到你得到一个完整的图像,然后对它执行操作并继续下一个。

这意味着您可以替换:

代码语言:javascript
复制
pack = s.recv(4196540)

使用类似这样的东西:

代码语言:javascript
复制
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字节的数据(假设是一个经过酸洗的图像),然后您就可以继续处理它了。

否则,您将不得不使用其他技术:例如,您可以定义自己的协议,其中第一个n字节是随后的文件大小,然后您就可以知道下一项需要多少数据。或者为每个项目打开新的连接(在另一端已关闭的套接字上的recv()不会阻塞,并产生b'')。

顺便说一句,最后一个注释还意味着,在发送最后一个图像后,服务器可以执行conn.close()并退出(或监听新的传入连接),我们可以在上面的代码片段中再做一次更改,即不是:

代码语言:javascript
复制
pack += s.recv(bufsize)

可以这样说:

代码语言:javascript
复制
buf = s.recv(bufsize)
if not buf:
    s.close()
    break  # end the "while True" loop
pack += buf

来停止在客户端的接收。

还有一个关于你提到的教程的注意事项。在一些微不足道的案例中。例如发送短字符串消息,虽然您不应该依赖它,但您通常很幸运,会将所有预期数据都放在一个块中recv

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60587912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档