当我发送“ sendto”的数据报时,IS有效载荷大小与字节长度相同。
我正在制作自己的协议,这是基于UDP的远程桌面协议。由于解决方案,我关心的是低潜伏期和时间效率。
在此之前,以前问题说UDP的最大安全有效负载大小为 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)
focus.py to sendto
中,您可以看到我调用该函数并以长度508的方式发送字节,这是以前的问题的意思吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不太确定您的问题。但是,您似乎将“安全有效载荷尺寸”解释为保证交付并拥有其他可靠性保证。事实并非如此。
无论使用哪个有效载荷大小,UDP都是不可靠的协议,可能导致数据包丢失,重新排序和数据包重复。不过,使用比“安全”更大的有效载荷大小会增加问题,因为这样的数据报可能会在IP级别分为多个片段,即使在交付过程中丢失了一个片段,数据报也会丢失。
因此,使用UDP,您永远不能假设所有数据包都是按顺序全部和订单的,就像您当前的代码一样。没有数据包大小会导致UDP是可靠的协议,因此需要在代码中处理数据报,重复和重新排序。
Try-Except对数据包丢失,数据包重复和重新排序根本无济于事
IPv4中UDP数据报的理论最大有效载荷大小为65507字节。 IPv6 Jumbograms可能会更大 - 请参阅。
但是来自下端:IPv4标准说,主机必须能够接受最多576个字节的数据报,而使用IPv6则是1280。删除IP和UDP标头,这将导致“安全”有效载荷大小为508对于IPv4(最大60个字节IPv4标头,固定8个字节UDP标头),为IPv6(固定40个字节IPv6标头),固定8个字节UDP标头)。
I'm not really sure about your question. But you seem to interpret "SAFE payload size" as guaranteed delivery and having other reliability guarantees. This is not the case.
No matter which payload size is used, UDP will be an unreliable protocol which might result in packet loss, packet reordering and packet duplication. Using a larger payload size than "SAFE" increases the problems though, because then datagrams might be split at the IP level into multiple fragments, and a datagram is lost even if a single fragment of it is lost during delivery.
So with UDP you can never assume that all packets are received exactly once and in order - as your code currently does. No packet size will result in UDP being a reliable protocol, so datagram loss, duplication and reordering need to be handled in the code.
Try-except does not help at all with packet loss, packet duplication and packet reordering
The theoretical maximum payload size of a UDP datagram in IPv4 is 65507 bytes. It might be even larger with IPv6 jumbograms - see the information about Length in Wikipedia: UDP datagram structure.
But to come from the lower end: the IPv4 standard says that hosts MUST be able to accept datagrams with up to 576 bytes, while with IPv6 this is 1280. Removing the IP and UDP header this results in a "safe" payload size of 508 for IPv4 (max 60 bytes IPv4 header, fixed 8 bytes UDP header) and 1232 for IPv6 (fixed 40 byte IPv6 header, fixed 8 bytes UDP header).