当我发送“ sendto”的数据报时,IS有效载荷大小与字节长度相同。

发布于 2025-02-07 20:11:08 字数 4424 浏览 1 评论 0 原文

我正在制作自己的协议,这是基于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的方式发送字节,这是以前的问题的意思吗?

I'm making my own protocol, it's Remote Desktop Protocol that based on UDP. I care with low latency and time efficientcy at cost of quality due to resolution.

According this previous question, It said the maximum SAFE payload size of UDP is 508. Does it mean I send 508 bytes every send?

Here is what am I doing:

# 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)

while for 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 to sendto in server.py, You can see I call that function and send bytes with length 508, is that previous question mean?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ゞ花落谁相伴 2025-02-14 20:11:08

它说UDP的最大安全有效载荷大小为508。这是否意味着我发送508个字节?

我不太确定您的问题。但是,您似乎将“安全有效载荷尺寸”解释为保证交付并拥有其他可靠性保证。事实并非如此。

无论使用哪个有效载荷大小,UDP都是不可靠的协议,可能导致数据包丢失,重新排序和数据包重复。不过,使用比“安全”更大的有效载荷大小会增加问题,因为这样的数据报可能会在IP级别分为多个片段,即使在交付过程中丢失了一个片段,数据报也会丢失。

因此,使用UDP,您永远不能假设所有数据包都是按顺序全部和订单的,就像您当前的代码一样。没有数据包大小会导致UDP是可靠的协议,因此需要在代码中处理数据报,重复和重新排序。

(从评论中)是的,我知道UDP是不可靠的协议,这就是为什么我使用许多Try-Except处理它。

Try-Except对数据包丢失,数据包重复和重新排序根本无济于事

(从评论中)实际上是508个字节(如以前的问题答案),或者应该是512个字节?

IPv4中UDP数据报的理论最大有效载荷大小为65507字节。 IPv6 Jumbograms可能会更大 - 请参阅

但是来自下端:IPv4标准说,主机必须能够接受最多576个字节的数据报,而使用IPv6则是1280。删除IP和UDP标头,这将导致“安全”有效载荷大小为508对于IPv4(最大60个字节IPv4标头,固定8个字节UDP标头),为IPv6(固定40个字节IPv6标头),固定8个字节UDP标头)。

It said the maximum SAFE payload size of UDP is 508. Does it mean I send 508 bytes every send?

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.

(from comment) Yes I know UDP is unreliable protocol that's why I'm using many try-except to handle it.

Try-except does not help at all with packet loss, packet duplication and packet reordering

(from comment) Is 508 bytes actually maximum (like that previous question answer) or it should be 512 bytes?

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文