我正在制作自己的協議,它是基于 UDP 的遠程桌面協議。由于解析度,我關心低延遲和時間效率,但要以質量為代價。
根據this previous question,它說UDP的最大SAFE有效負載大小是508。這是否意味著我每次發送都發送 508 個位元組?
這是我在做什么:
# RDP server.py
import cv2 as cv
import numpy as np
from time import time
from mss import mss
import pyautogui as pag
import socket
screenSize = pag.size()
# Optimization Config
'''
2160p = (3840, 2160)
1440p = (2560, 1440)
1080p = (1920, 1080)
720p = (1280, 720)
480p = (640, 480)
360p = (480, 360)
240p = (426, 240)
144p = (256, 144)
'''
# resolution = screenSize # Uncomment for using server resolution
resolution = (640, 480) # Uncomment for using common resolution
compression = 5 # 100 means no compress, 0 is highest compression!
encodeParam = (int(cv.IMWRITE_JPEG_QUALITY), compression)
# Server Config
addrPortServer = ('0.0.0.0', 20001)
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPServerSocket.bind(addrPortServer)
UDPServerSocket.settimeout(0.5)
payloadSize = 508
monitor = {"top": 0, "left": 0, "width": screenSize[0], "height": screenSize[1]}
receivePeriode = time()
addrPortClient = None
print('RDU Server is running...')
with mss() as sct:
while True:
loopTime = time()
if loopTime - receivePeriode > 3:
try:
dataFromClient, addrPortClient = UDPServerSocket.recvfrom(1024)
if b'shutdown' in dataFromClient:
print('Shutdown from client!')
break
except:
addrPortClient = None
receivePeriode = loopTime
if addrPortClient is not None:
frame = np.asarray(sct.grab(monitor))
frame = cv.cvtColor(frame, cv.COLOR_BGRA2BGR)
frame = cv.resize(frame, dsize=resolution)
isSucceed, encImg = cv.imencode('.jpg', frame, encodeParam)
bytesToSend = encImg.tobytes()
for i in range(0, len(bytesToSend), payloadSize):
UDPServerSocket.sendto(bytesToSend[i:i payloadSize], addrPortClient)
# print(time() - loopTime)
而對于client.py
# RDP client.py
import cv2 as cv
import numpy as np
from time import time
from mss import mss
import pyautogui as pag
import socket
# Client Config
addrPortServer = ('127.0.0.1', 20001)
UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPClientSocket.settimeout(1)
payloadSize = 508
recvFromSize = payloadSize * 2
defaultFrame = np.fromfile('./waiting-server.jpg', dtype=np.uint8)
oldBytesFrame = defaultFrame
screenSize = pag.size() # uncomment for full screen
screenSize = (int(screenSize[0]*0.75), int(screenSize[1]*0.75)) # uncomment for windowed mode
sendPeriode = 0
currentDelay = []
avgDelay = 0
updateDelayTime = time()
with mss() as sct:
while True:
loopTime = time()
if loopTime - sendPeriode > 3:
UDPClientSocket.sendto(b'?', addrPortServer)
sendPeriode = loopTime
bytesFrame = b''
lenBytesFromServer = payloadSize
try:
while lenBytesFromServer == payloadSize:
bytesFromServer = UDPClientSocket.recvfrom(recvFromSize)[0]
lenBytesFromServer = len(bytesFromServer)
bytesFrame = bytesFromServer
except:
bytesFrame = oldBytesFrame
try:
frame = cv.imdecode(np.frombuffer(bytesFrame, dtype=np.uint8), 1)
frame = cv.resize(frame, screenSize)
except Exception as e:
print(e)
frame = cv.imdecode(np.frombuffer(oldBytesFrame, dtype=np.uint8), 1)
frame = cv.resize(frame, screenSize)
# FPS Management
currentDelay.append(time() - loopTime)
if time() - updateDelayTime > 1:
avgDelay = sum(currentDelay) / len(currentDelay)
currentDelay = []
print(len(bytesFrame))
updateDelayTime = time()
frame = cv.putText(frame,
text = str(avgDelay),
org = (10,40),
fontFace = cv.FONT_HERSHEY_SIMPLEX,
fontScale = 1,
thickness = 2,
lineType = cv.LINE_AA,
color = (0,0,255))
try:
cv.imshow('RDU Client', frame)
except:
cv.imshow('RDU Client', cv.imdecode(defaultFrame,1))
if cv.waitKey(1) == ord('q'):
cv.destroyAllWindows()
break
oldBytesFrame = bytesFrame
UDPClientSocket.sendto(b'shutdown', addrPortServer)
關注sendtoserver.py,你可以看到我呼叫了那個函式并發送了長度為 508 的位元組,之前的問題是什么意思?
uj5u.com熱心網友回復:
它說 UDP 的最大 SAFE 有效負載大小為 508。這是否意味著我每次發送都發送 508 個位元組?
我不太確定你的問題。但是您似乎將“安全有效載荷大小”解釋為保證交付并具有其他可靠性保證。不是這種情況。
無論使用哪種有效載荷大小,UDP 都將是一個不可靠的協議,可能會導致資料包丟失、資料包重新排序和資料包重復。但是,使用比“SAFE”更大的有效載荷會增加問題,因為這樣資料報可能會在 IP 級別被拆分為多個片段,并且即使資料報的單個片段在傳遞程序中丟失,資料報也會丟失。
因此,使用 UDP,您永遠不能假設所有資料包都按順序接收一次 - 正如您的代碼當前所做的那樣。任何資料包大小都不會導致 UDP 成為可靠的協議,因此需要在代碼中處理資料報丟失、重復和重新排序。
(來自評論)是的,我知道 UDP 是不可靠的協議,這就是為什么我使用許多 try-except 來處理它的原因。
Try-except 對資料包丟失、資料包重復和資料包重新排序完全沒有幫助
(來自評論)實際上是最大 508 個位元組(就像之前的問題答案一樣)還是應該是 512 個位元組?
IPv4 中 UDP 資料報的理論最大有效負載大小為 65507 位元組。IPv6 jumbograms 可能更大 - 請參閱 Wikipedia 中有關Length的資訊:UDP datagram structure。
但是來自低端:IPv4 標準規定主機必須能夠接受最多 576 位元組的資料報,而 IPv6 則為 1280。洗掉 IP 和 UDP 標頭會導致“安全”有效負載大小為 508對于 IPv4(最大 60 位元組 IPv4 報頭,固定 8 位元組 UDP 報頭)和 1232 用于 IPv6(固定 40 位元組 IPv6 報頭,固定 8 位元組 UDP 報頭)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/492898.html
上一篇:通過JNI系結套接字
