C#UDP数据包丢失但所有数据包都到达(WireShark)

正如标题所说我在C#中遇到UDP问题。 我正在尝试为DayZ游戏的rcon协议构建一个库。

我的问题是我没有收到我应该收到的每一个数据包。 发送命令后,服务器回复分裂答案。 包头包含总包数和当前包的索引。 现在,如果我应该获得17个数据包,我的应用程序中只能获得8-15个数据包。

在使用WireShark进行测试后,我现在知道所有包都到达了我的计算机。 他们只是不被我的应用程序或类似的东西认可。

我的实际问题是:是否可以防止丢失我的网卡和我的应用程序之间的包裹? 或者为什么会这样?

这是我目前的代码。 它非常脏,因为我在按预期工作后撕开它:

private Socket _udpClient; private Thread _receiverThread; private Thread _workerThread; private Queue _packetQueue; private PacketBuffer[] MessageBuffer; private byte SenderSequence = 0; private IPEndPoint connection; public RCon(IPAddress ip, int port) { connection = new IPEndPoint(ip, port); _udpClient = new Socket(connection.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp); _udpClient.Connect(connection); MessageBuffer = new PacketBuffer[256]; _packetQueue = new Queue(); _receiverThread = new Thread(new ThreadStart(ReceiveCallback)); _receiverThread.IsBackground = true; _receiverThread.Priority = ThreadPriority.AboveNormal; _receiverThread.Start(); _workerThread = new Thread(new ThreadStart(WorkerCallback)); _workerThread.IsBackground = true; _workerThread.Start(); } public void Login(string password) { LoginPacket packet = new LoginPacket(password); _udpClient.Send(packet.Bytes); } public void SendCommand(string command) { CommandPacket packet = new CommandPacket(SenderSequence, command); SenderSequence++; _udpClient.Send(packet.Bytes); } private void ReceiveCallback() { while (true) { byte[] buffer = new byte[1036]; if (_udpClient.Receive(buffer) > 0) _packetQueue.Enqueue(buffer); } } private void WorkerCallback() { while (true) { if (_packetQueue.Count > 0) { byte[] buffer = _packetQueue.Dequeue(); if (buffer != null) { try { Packet receivedPacket = Packet.ParseIncoming(buffer); OnPacketReceived(new PacketReceivedEventArgs(receivedPacket)); switch (receivedPacket.Type) { case PacketType.Message: OnMessageReceived(new MessageReceivedEventArgs(receivedPacket.Content)); MessageCallbackPacket packet = new MessageCallbackPacket(receivedPacket.SequenceNumber); _udpClient.Send(packet.Bytes); break; case PacketType.CommandCallback: if (MessageBuffer[receivedPacket.SequenceNumber] == null) MessageBuffer[receivedPacket.SequenceNumber] = new PacketBuffer(receivedPacket); else MessageBuffer[receivedPacket.SequenceNumber].AddPacket(receivedPacket); if (MessageBuffer[receivedPacket.SequenceNumber].IsComplete) OnCommandCallback(new CommandCallbackEventArgs(MessageBuffer[receivedPacket.SequenceNumber].GetContent())); break; } } catch (ArgumentException) { } catch (OverflowException) { } catch (FormatException) { } } } } } 

这通常是因为您没有足够快地使用数据报,因此内核套接字缓冲区已满,网络堆栈开始丢弃新到达的数据包。 一些要点:

  • 增加套接字上的接收缓冲区,
  • 不要在每次迭代时获取锁 – 尽可能多地读取,然后将数据放入队列,
  • 考虑非阻塞方法而不是线程。