python 中通过 TCP 套接字传输视频的代码;需要帮助理解其中的一部分
Code for streaming video over tcp socket in python; need help understanding parts of it
我得到了将视频从客户端流式传输到服务器的代码:
客户:
import cv2, imutils
import mss
import numpy
from win32api import GetSystemMetrics
import pickle
import socket, struct
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = "IPADRESS"
port = 9999
client_socket.connect((host_ip,port))
with mss.mss() as sct:
monitor = {"top": 0, "left": 0, "width": GetSystemMetrics(0), "height": GetSystemMetrics(1)}
while True:
img = numpy.array(sct.grab(monitor))
frame = imutils.resize(img, width=1400)
a = pickle.dumps(frame)
message = struct.pack("Q",len(a))+a
client_socket.send(message)
服务器:
import cv2, imutils
import numpy as np
import pickle, struct
import socket
import threading
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = "IP_ADRESS"
port = 9999
socket_address = (host_ip,port)
server_socket.bind(socket_address)
server_socket.listen()
print("Listening at",socket_address)
def show_client(addr,client_socket):
try:
print('CLIENT {} CONNECTED!'.format(addr))
if client_socket: # if a client socket exists
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4*1024)
if not packet:
break
data+=packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q",packed_msg_size)[0]
while len(data) < msg_size:
data += client_socket.recv(4*1024)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = pickle.loads(frame_data)
cv2.imshow("Screen", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
client_socket.close()
except Exception as e:
print(e)
print(f"CLINET {addr} DISCONNECTED")
pass
while True:
client_socket,addr = server_socket.accept()
thread = threading.Thread(target=show_client, args=(addr,client_socket))
thread.start()
print("TOTAL CLIENTS ",threading.activeCount() - 1)
很多代码来自一个名为“pyshine”的 youtuber,一切正常,但我不明白,这段代码的特定部分到底在做什么。
这些是部分:
首先在客户端代码中:
message = struct.pack("Q",len(a))+a
我知道它会根据泡菜的长度做一些事情,并且会在上面附加泡菜,但不会更多。
服务器代码中的第二个:
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4*1024)
if not packet:
break
data+=packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q",packed_msg_size)[0]
while len(data) < msg_size:
data += client_socket.recv(4*1024)
frame_data = data[:msg_size]
随着打印出一些值,我肯定理解得更好了,但是整个过程,它是如何得到最终的“frame_data”的,对我来说仍然是个谜。所以,如果有人能向我解释那里的过程,我将不胜感激。
socket
是原始对象,它不关心你发送什么数据。您可以发送两个帧,客户端可以将其作为单个包获取,也可以将其作为多个小包获取 - socket
不关心第一个 frame
的结尾在哪里。要解决此问题,此代码首先发送 len(data)
,然后发送 data
。它使用 struct("Q")
,所以这个值 len(data)
总是 8 bytes
。通过这种方式,接收器知道它必须接收多少 data
才能拥有完整的帧 - 首先它获得 8 bytes
才能获得 len(data)
,然后它使用该值获得所有 data
。这就是第二个代码所做的——它重复 recv()
直到它得到所有 data
。它还会检查它是否没有从下一帧获得 data
- 并将此部分保留为 data[payload_size:]
以便在下一帧/
中使用它
如果您将在双方使用相同的规则 - 发送方首先使用 size
发送 8 bytes
,然后发送 data
,接收方首先使用 8 bytes
size
然后得到 data
(使用 size
)——然后你就定义了 protocol
。 (类似于其他协议:HTTP
(HyperText Transfer Protocol
),FTP
(File Transfer Protocol
),SMTP
(Send Mail Transfer Protocol
)等)
我得到了将视频从客户端流式传输到服务器的代码:
客户:
import cv2, imutils
import mss
import numpy
from win32api import GetSystemMetrics
import pickle
import socket, struct
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = "IPADRESS"
port = 9999
client_socket.connect((host_ip,port))
with mss.mss() as sct:
monitor = {"top": 0, "left": 0, "width": GetSystemMetrics(0), "height": GetSystemMetrics(1)}
while True:
img = numpy.array(sct.grab(monitor))
frame = imutils.resize(img, width=1400)
a = pickle.dumps(frame)
message = struct.pack("Q",len(a))+a
client_socket.send(message)
服务器:
import cv2, imutils
import numpy as np
import pickle, struct
import socket
import threading
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = "IP_ADRESS"
port = 9999
socket_address = (host_ip,port)
server_socket.bind(socket_address)
server_socket.listen()
print("Listening at",socket_address)
def show_client(addr,client_socket):
try:
print('CLIENT {} CONNECTED!'.format(addr))
if client_socket: # if a client socket exists
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4*1024)
if not packet:
break
data+=packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q",packed_msg_size)[0]
while len(data) < msg_size:
data += client_socket.recv(4*1024)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = pickle.loads(frame_data)
cv2.imshow("Screen", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
client_socket.close()
except Exception as e:
print(e)
print(f"CLINET {addr} DISCONNECTED")
pass
while True:
client_socket,addr = server_socket.accept()
thread = threading.Thread(target=show_client, args=(addr,client_socket))
thread.start()
print("TOTAL CLIENTS ",threading.activeCount() - 1)
很多代码来自一个名为“pyshine”的 youtuber,一切正常,但我不明白,这段代码的特定部分到底在做什么。 这些是部分:
首先在客户端代码中:
message = struct.pack("Q",len(a))+a
我知道它会根据泡菜的长度做一些事情,并且会在上面附加泡菜,但不会更多。
服务器代码中的第二个:
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4*1024)
if not packet:
break
data+=packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q",packed_msg_size)[0]
while len(data) < msg_size:
data += client_socket.recv(4*1024)
frame_data = data[:msg_size]
随着打印出一些值,我肯定理解得更好了,但是整个过程,它是如何得到最终的“frame_data”的,对我来说仍然是个谜。所以,如果有人能向我解释那里的过程,我将不胜感激。
socket
是原始对象,它不关心你发送什么数据。您可以发送两个帧,客户端可以将其作为单个包获取,也可以将其作为多个小包获取 - socket
不关心第一个 frame
的结尾在哪里。要解决此问题,此代码首先发送 len(data)
,然后发送 data
。它使用 struct("Q")
,所以这个值 len(data)
总是 8 bytes
。通过这种方式,接收器知道它必须接收多少 data
才能拥有完整的帧 - 首先它获得 8 bytes
才能获得 len(data)
,然后它使用该值获得所有 data
。这就是第二个代码所做的——它重复 recv()
直到它得到所有 data
。它还会检查它是否没有从下一帧获得 data
- 并将此部分保留为 data[payload_size:]
以便在下一帧/
如果您将在双方使用相同的规则 - 发送方首先使用 size
发送 8 bytes
,然后发送 data
,接收方首先使用 8 bytes
size
然后得到 data
(使用 size
)——然后你就定义了 protocol
。 (类似于其他协议:HTTP
(HyperText Transfer Protocol
),FTP
(File Transfer Protocol
),SMTP
(Send Mail Transfer Protocol
)等)