我正在使用python套接字将图像从笔记本电脑的摄像头(客户端)传输到raspberry pi(服务器)。下面是它的运行方式,我连接到套接字,然后我的客户机等待信号以便拍照。当信号(来自我的服务器)被发送时,我的客户机拍了一张照片并按顺序发送以下数据;首先,表示图片大小的数字的长度(例如,对于10000字节,数字为5,对于100000字节,数字为6,依此类推),然后发送实际大小,最后以字节字符串的形式发送照片。这个过程重复了无数次
Client.py
import cv2
import socket
import os
def send_msg(s, msg):
s.sendall(msg)
s = socket.socket()
port = 24999
ip = '192.168.1.3'
s.connect((ip, port))
video = cv2.VideoCapture(0)
s.recv(1) #Wait until data is sent
while True:
_, img = video.read()
img = cv2.resize(img, (0,0), fx = 0.4, fy = 0.4) #reduce image size
cv2.imwrite("test.jpg", img) #save img
size = os.path.getsize("test.jpg") #get image size
img_str = cv2.imencode('.jpg', img)[1].tostring() #convert to bytes string
sizenum = str(len(str(size))) #how many digits the image size contains
send_msg(s, sizenum.encode())
send_msg(s, str(size).encode('utf-8')) #send actual image size
send_msg(s, img_str) #finally send the image
s.recv(1) #Wait until data is sent
Server.py
import socket
import ast
def send_msg(client, msg):
client.sendall(msg+b'\r\n')
def recvall(sock, n):
# Helper function to recv n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
def take_photo(cl):
#RECEIVE LENGTH OF SIZE
while True:
lensize = cl.recv(1)
lensize = lensize.decode('utf-8')
if lensize != "":
break
print("Size is a",lensize,"-digit number")
lensize = lensize.replace("\n","").replace(" ","").replace("\r","")
#RECEIVE SIZE
size_pic = recvall(cl,ast.literal_eval(lensize)).decode('utf-8')
size_pic = size_pic.replace("\n","").replace(" ","").replace("\r","")
print("Exact size is",size_pic)
#RECEIVE PHOTO
return lensize,size_pic,bytearray(recvall(cl,ast.literal_eval(size_pic)))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("192.168.1.3",24999))
s.listen(1)
while True:
cl_image, addr = s.accept()
break
while True:
try:
send_msg(cl_image, b"1") #Send signal
size1, size2, photo = take_photo(cl_image)
print(photo)
except KeyboardInterrupt:
print("error")
s.close()
问题 运行服务器时,在运行几秒钟后会出现问题(有时在引发任何异常前仅运行1秒,有时运行5秒或更长时间)
示例运行1(服务器)
Size is a 5 -digit number
Exact size is 21263
7294 from 21263 Not all bytes were read
18974 from 21263 Not all bytes were read
Size is a 5 -digit number
Exact size is 21226
2915 from 21226 Not all bytes were read
4375 from 21226 Not all bytes were read
11675 from 21226 Not all bytes were read
18975 from 21226 Not all bytes were read
Size is a 5 -digit number
Exact size is 21412
2915 from 21412 Not all bytes were read
7295 from 21412 Not all bytes were read
14595 from 21412 Not all bytes were read
Size is a . -digit number
Traceback (most recent call last):
File "sending_test.py", line 46, in <module>
size1, size2, photo = take_photo(cl_image)
File "sending_test.py", line 27, in take_photo
size_pic = recvall(cl,ast.literal_eval(lensize)).decode('utf-8')
File "/usr/lib/python3.7/ast.py", line 46, in literal_eval
node_or_string = parse(node_or_string, mode='eval')
File "/usr/lib/python3.7/ast.py", line 35, in parse
return compile(source, filename, mode, PyCF_ONLY_AST)
File "<unknown>", line 1
.
示例运行2(服务器)
Size is a 5 -digit number
Exact size is 20653
7294 from 20653 Not all bytes were read
14594 from 20653 Not all bytes were read
18974 from 20653 Not all bytes were read
Size is a 5 -digit number
Exact size is 20595
2915 from 20595 Not all bytes were read
8755 from 20595 Not all bytes were read
10215 from 20595 Not all bytes were read
18975 from 20595 Not all bytes were read
Traceback (most recent call last):
File "sending_test.py", line 46, in <module>
size1, size2, photo = take_photo(cl_image)
File "sending_test.py", line 21, in take_photo
lensize = lensize.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
我还在服务器的循环中插入了一个print(photo)命令,以查看发生了什么,这就是结果(参见最后一行与其他行的比较)
Size is a 3 -digit number
Exact size is 828
bytearray(b'\xff\xd8\xff.......\xff\xd9')
Size is a 3 -digit number
Exact size is 831
bytearray(b'\xff\xd8\xff......\xff\xd9')
Size is a 3 -digit number
Exact size is 831
bytearray(b'\xff\xd8\xff.......\xff\xd9383')
这意味着它读取的字节数应该多一些(3)(3表示大小长度,83来自图像大小,类似于(83x)
根据评论,我做了如下几点修改:
与其将JPEG写入磁盘,然后计算其大小,然后再次将其编码到内存并转换为字符串并发送,我只是将JPEG编码到内存缓冲区,获取其大小并发送
我没有发送一个字符串来表示视频帧中的字节数,而是将字节数作为4字节网络顺序整数发送。它使生活更容易
它在我的机器上似乎工作得很可靠
这是客户:
这是服务器:
关键词:TCP套接字、流、基于流、基于流、消息、基于消息、成帧协议、成帧、htonl、网络顺序、数据包、主数据包
相关问题 更多 >
编程相关推荐