我得到了用于將視頻從客戶端流式傳輸到服務器的代碼:
客戶:
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”,對我來說仍然是個謎。所以我真的很感激,如果有人能向我解釋那里的流程。
uj5u.com熱心網友回復:
socket是原始物件,它不在乎您發送什么資料。您可以發送兩個幀,客戶端可以將其作為單個包獲取,也可以將其獲取為多個小包 -socket不關心第一個結束的位置frame。要解決此問題,此代碼首先發送len(data),然后發送data。它使用struct("Q")所以這個值len(data)總是8 bytes. 通過這種方式接收器知道data它必須接收多少才能擁有完整的幀 - 首先它會8 bytes得到len(data),然后它使用這個值來得到所有data。這就是第二個代碼所做的 - 它重復recv()直到全部完成data。它還檢查它是否不是data來自下一幀 - 并保留這部分data[payload_size:]以便將它用于下一幀/
如果您將在雙方使用相同的規則 - 發送者首先發送8 byteswithsize和 next data,接收者首先獲取8 byteswithsize然后獲取data(使用size) - 那么您已經定義了protocol. (類似于其他協議:HTTP(HyperText Transfer Protocol), (FTP),File Transfer Protocol(SMTP),Send Mail Transfer Protocol等等)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/360427.html
上一篇:服務器超時C#
