【问题标题】:Losing packets due to occurence of very unlikely situation?由于发生非常不可能的情况而丢失数据包?
【发布时间】:2012-02-07 16:29:28
【问题描述】:

我最近一直在使用 UDP 套接字。我读过UDP没有内部缓冲区。这意味着如果一个数据包到达并且没有人在等待它,它就会被丢弃。我想到了一种不太可能发生的情况。但如果发生,可能会导致问题。

byte[] buffer = new byte[1024];
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(...);
while (true)
{
    EndPoint remote = new IPEndPoint(IPAddress.Any, 0);
    socket.ReceiveFrom(buffer, ref remote);
    socket.SendTo(remote, new byte[] { 1, 2, 3, 4 });
}

如果在执行 SendTo 时,这是一个非异步方法(因此它会阻塞它运行的线程,直到它完成,即完成发送数据),另一个来自不同主机的数据包到达?由于没有执行 ReceiveFrom 方法,数据包会被转储吗?

假设“是”,我已经考虑过使用异步套接字。它看起来像这样:

Socket socket;    
byte[] buffer;

void StartServer()
{
    buffer = new byte[1024];
    socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    socket.Bind(...);
    EndPoint remote = new IPEndPoint(IPAddress.Any, 0);

    StartReceive();
}

void StartReceive()
{
    socket.BeginReceiveFrom(buffer, 0, buffer.Size, SocketFlags.None, ref remote, OnReceive, null);
}

void OnReceive(IAsyncState state)
{
    EndPoint epRemote = new IPEndPoint(IPAddress.Any, 0);
    socket.EndReceiveFrom(state, ref epRemote);
    socket.BeginSendTo(new byte[] { 1, 2, 3, 4 }, 0, 4, SocketFlags.None, epRemote, null, null);
    StartReceive();
}

当 onReceive 方法被 socket.BeginReceiveFrom 调用时,它的代码被执行。由于此代码使用 BeginSendTo,因此它不会阻塞线程。但是如果数据包在 OnReceive 调用 StartReceive 之前到达怎么办?它会丢失吗?

所以我的问题: UDP 数据包是否被缓冲,如果是,缓冲多长时间?

【问题讨论】:

    标签: c# sockets asynchronous udp buffer


    【解决方案1】:

    不,框架的内部将确保数据包在被解析之前处于队列中。这通常是通过使用一个缓冲区来实现的,该缓冲区将数据包保存一段时间,直到接收者真正收到数据包。

    有多个层可以确保这一点,要了解更多信息,并且因为您使用 OSI 的应用层,您应该研究 OSI 以深入理解这些概念。

    【讨论】:

    • UDP 数据包可以随时丢弃。当缓冲区已满时,新收到的数据包将被丢弃。
    • 如果他们按照你说的那样排队,那就违反了UDP协议标准。
    • 我实际上同意这一点,但在应用层它不违反 UDP 标准,实际上一个 UDP 数据包可能不会到达目的地,但如果它确实到达它不会被丢弃,除非你正确添加缓冲区已满。
    • 啊,是的,在应用层,我猜是不同的东西。
    • 对,UDP 在第 4 层,而你的应用程序在第 7 层工作,所以这不是你关心的问题,你的音乐会可能是确保它们是否到达,我猜你不能做更多.
    【解决方案2】:

    UDP 确实会在系统的较低级别进行缓冲,但是当缓冲区已满并且有更多 UDP 数据包到达时,它们会被丢弃。 UDP 数据包可以在发送方和接收方之间的任何地方丢弃。如果您想确保收到所有内容,您应该按照特定顺序为每个发送/接收的数据包保留某种 ID,以便您可以查看是否缺少某些内容并请求重新发送。

    【讨论】:

      猜你喜欢
      • 2020-05-14
      • 2022-08-22
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      相关资源
      最近更新 更多