我最近一直在使用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数据包是否完全缓冲,如果是,则持续多长时间?
答案 0 :(得分:2)
不,框架的内部将确保数据包在解析之前一直处于空闲状态。这通常通过使用缓冲区来实现,该缓冲区将数据包保存一段时间,直到接收方实际获取数据包为止。
有多个层可以确保这一点,有关更多信息,并且因为您使用OSI的应用层,您应该学习OSI以深入理解这些概念。
答案 1 :(得分:2)
UDP确实在系统的较低级别进行缓冲,但是当缓冲区已满且更多UDP数据包到达时,它们将被删除。可以在发送方和接收方之间的任何地方丢弃UDP数据如果您想确保收到所有内容,则应按特定顺序为每个发送/接收的数据包保留某种ID,以便您可以查看是否缺少某些内容并请求再次发送。