gpt4 book ai didi

Python 套接字和 Opencv - ConnectionResetError : [WinError 10054]

转载 作者:太空宇宙 更新时间:2023-11-03 20:09:30 29 4
gpt4 key购买 nike

编辑:澄清一下:它确实可以编译,但在流加载后几乎立即崩溃。 它确实连接正确。

所以,我已经尝试了很长时间来完成我的这个项目。我想做的是使用 cv2 通过套接字发送视频源。它通过 LAN 运行,而不是通过 WAN 运行。我收到以下错误:

"ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host"

客户端代码(发送视频):

import cv2
import numpy as np
import socket
import pickle

host = "<insert public ip of recipient>"
port = 7643

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # declares s object with two parameters
s.connect((host, port)) # connects to the host & port
cap = cv2.VideoCapture(1)
while cap.isOpened(): # while camera is being used
ret, frame = cap.read() # reads each frame from webcam
if ret:
encoded = pickle.dumps(cv2.imencode(".jpg", frame)[1]) # encoding each frame, instead of sending live video it is sending pictures one by one
s.sendall(encoded)
if cv2.waitKey(1) & 0xFF == ord("q"): # wait until key was pressed once and
break
cap.release()
cv2.destroyAllWindows()

接收者代码(接收视频):

import cv2
import socket
import pickle

host = "192.168.1.186"
port = 7643
boo = True

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # declares s object with two parameters
s.bind((host, port)) # tells my socket object to connect to this host & port "binds it to it"
s.listen(10) # tells the socket how much data it will be receiving.

conn, addr = s.accept()
while boo:
try:
pictures = conn.recv(256000) # creates a pictures variable that receives the pictures with a max amount of 128000 data it can receive
decoded = pickle.loads(pictures) # decodes the pictures
frame = cv2.imdecode(decoded, cv2.IMREAD_COLOR) # translates decoded into frames that we can see!
cv2.imshow("unique", frame)
if cv2.waitKey(1) & 0xFF == ord("q"): # wait until q key was pressed once and
break
except:
print("Something is broken...")
boo = False
cv2.destroyAllWindows()
s.close()

最佳答案

通过 LAN 运行此程序时,您显然很幸运。您的代码没有正确地将图像流从发送者发送到接收者,因为像 TCP 这样的流套接字本质上使用起来有点复杂。主要问题是您的发送方没有沟通每个图像的结束位置和下一个图像的开始位置,并且您的接收方同样没有将其读取的数据组织到单个完整图像中。

也就是说,socket.sendall() 不会将其数据的结尾传达给接收者;您需要将该信息包含在您发送的实际数据中。

错误处理

但在修复此问题之前,您应该修复收件人的错误处理,以便获得更有用的错误消息。当你写的时候

except:
print("Something is broken...")

您正在丢弃一些对您有更多帮助的东西,例如“EOFError:Ran out of input”或“_pickle.UnpicklingError”。不要丢弃该信息。相反,打印它:

except:
traceback.print_exc()

或者重新加注:

except Exception as err:
# do whatever you want to do first
raise err

或者,由于您想让它使您的程序崩溃,并且只想先进行清理,因此可以在 finally 子句中进行清理,不需要 except:

try:
# your code
finally:
# the cleanup

流套接字和发送者

回到您的套接字代码,您正在使用流套接字。它们发送字节流,虽然您可以指望它们以正确的顺序到达,但您不能指望它们何时到达。如果您发送 b"something",然后发送 b"something else",您可能会同时收到 b"somethingsomething else"b"somet" 然后是 b"hing" 等等。您的接收者需要知道每条消息之间的分界线在哪里,因此第一步是使该分界线成为 消息之间的分界线。有几种方法可以做到这一点:

  • 使所有消息的大小相同。由于您将它们编码为 JPEG,并且根据压缩方式的不同,它们可能具有不同的大小,因此这会有点复杂,而且可能不是您想要的。
  • 以字节为单位发送实际标记,例如换行符 b"\n"b"\n\r"。这对于您的情况来说比较复杂。
  • 在发送之前发送每条消息的大小。对于您的情况来说,这应该是最简单的。

当然,如果您现在发送邮件的大小,那么这就像另一封邮件一样,并且您的收件人需要知道此大小的邮件在哪里结束。您可以再次以换行符结束大小消息:

s.sendall("{}\n".format(len(encoded)).encode("ascii"))

或者你可以将其打包成固定长度的字节数,例如 4:

s.sendall(struct.pack("!i", len(encoded)))

接收者

尽管 socket.recv() 可以返回部分消息或多条消息的一部分,但您的接收器代码现在需要读取完整消息。您可以保留传入数据的缓冲区。添加到末尾,然后从前面删除完整消息:

buf = ''
while boo:
new_data = s.recv(4096)
if not new_data:
# exit, because the socket has been closed
buf += new_data
# if there's a full message at the beginning of buf:
# remove that message, but leave the rest in buf
# process that message
# else:
# nothing, just go back to receiving more

当然,要找到完整的消息,首先您需要获取完整大小的消息。如果您使用 struct.pack 将所有大小消息编码为 4 个字节,则只需接收数据,直到 buf 的长度为 4 个或更多字节,然后将其拆分为大小和剩余的内容数据:

message_size = struct.unpack("!i", buf[:4])[0]
buf = buf[4:]

然后对图像消息执行相同的操作。接收数据,直到您拥有至少 message_size 字节的数据,将缓冲区拆分为第一条图像消息,您可以解码和显示该消息,并将其余部分保留在缓冲区中。

安全

documentation for pickle说:

Warning: The pickle module is not secure. Only unpickle data you trust. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Never unpickle data that could have come from an untrusted source, or that could have been tampered with.

就您而言,理论上其他人可以在您选择的端口上连接到您的 IP,并将他们想要的任何内容发送给您的收件人。如果这只是一个玩具项目,不会一直运行,那么可能性很低。

关于Python 套接字和 Opencv - ConnectionResetError : [WinError 10054],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58784347/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com