C # UDP Paketverlust obwohl alle Pakete ankommen (WireShark)
Wie der Titel schon sagt, habe ich ein Problem mit UDP in C #. Ich versuche, eine Bibliothek für das RCON-Protokoll des Spiels DayZ zu erstellen.
Mein Problem ist, dass ich nicht jedes Paket erhalte, das ich erhalten sollte. Nach dem Senden eines Befehls antwortet der Server mit einer geteilten Antwort. Der Paketkopf enthält die Gesamtpaketanzahl und den Index des aktuellen Pakets. Wenn ich jetzt 17 Pakete bekomme, bekomme ich in meiner Anwendung nur 8-15 Pakete.
Nach dem Testen mit WireShark weiß ich jetzt, dass alle Pakete auf meinem Computer ankommen. Sie werden von meiner Bewerbung oder ähnlichem einfach nicht erkannt.
Meine eigentliche Frage lautet: Kann ich verhindern, dass Pakete zwischen meiner Netzwerkkarte und meiner Anwendung verloren gehen? oder warum passiert das
Hier ist mein aktueller Code. Es ist ziemlich schmutzig, weil ich es auseinander gerissen habe, nachdem ich nicht wie erwartet gearbeitet habe:
private Socket _udpClient;
private Thread _receiverThread;
private Thread _workerThread;
private Queue<byte[]> _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<byte[]>();
_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) { }
}
}
}
}