由于发生非常不可能的情况丢失数据包?

时间:2012-02-07 16:29:29

标签: c# sockets asynchronous udp buffer

我最近一直在使用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();
}

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

所以我的问题: UDP数据包是否完全缓冲,如果是,则持续多长时间?

2 个答案:

答案 0 :(得分:2)

不,框架的内部将确保数据包在解析之前一直处于空闲状态。这通常通过使用缓冲区来实现,该缓冲区将数据包保存一段时间,直到接收方实际获取数据包为止。

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

答案 1 :(得分:2)

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