2016-04-30 7 views
1

Ich verwende derzeit D, um einen kleinen UDP-Server für ein Spiel zu schreiben. Das Problem besteht darin, dass einige empfangene Pakete nicht mit der Länge der tatsächlichen Pakete übereinstimmen (angezeigt über wireshark).D receiveVon Empfangen des vollständigen Pakets

Zum Beispiel sendet der Client ein 110-Byte-Paket über das Netzwerk, das unter Wireshark angezeigt wird. Aber der D-Code erhält nur 7 Bytes! Es gibt keine anderen 7-Byte-Pakete, die vom Client über das Netzwerk gesendet werden.

Die 7 Bytes von D stimmen mit den ersten 7 Bytes des 110-Byte-Pakets überein. Ich glaube, es ist ein Problem mit der Socket-Bibliothek, da ich an nichts anderes denken kann, das dieses Problem verursachen könnte.

Das Problem tritt immer am gleichen Punkt und genau dasselbe Paket auf. Wenn ignoriert, wird das Problem für bestimmte Pakete fortgesetzt.

Bitte beachten Sie, dass mehrere Dateien in diesem Projekt sind, so dass ich eingeschlossen snips des Codes unter:

this(in Logger logger, string bindInterface = "0.0.0.0", ushort bindPort = 19132) { 
    this.logger = logger; 
    socket = new UdpSocket(AddressFamily.INET); 
    bindAddress = new InternetAddress(bindInterface, bindPort); 
} 

void bind(uint sendBufferSize = 1024 * 1024, uint recvBufferSize = 1024 * 1024) { 
    socket.bind(bindAddress); 

    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.BROADCAST, true); 
    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.SNDBUF, sendBufferSize); 
    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVBUF, recvBufferSize); 
    socket.blocking = false; 
} 

bool recv(ref Address address, ref byte[] buffer) { 
    auto length = socket.receiveFrom(buffer, SocketFlags.NONE, address); 
    if(length > 0) { 
     buffer.length = length; 
     debug logger.logDebug(to!string(length) ~ " Packet IN: " ~ to!string(cast(ubyte[]) buffer)); 
     return true; 
    } 
    buffer = null; 
    return false; 
} 

...

Address a; 
    byte[] data = new byte[1024 * 1024]; 
    while(max-- > 0 && socket.recv(a, data)) { 
     handlePacket(a, data); 
    } 

Voll Quelle kann here.

finden

Jede Hilfe würde sehr geschätzt werden.

Der Kunde ist

+0

Können Sie den genauen Inhalt der gesamten gesendeten Nachricht sehen? Nicht, was Sie glauben, aber was Inhalt wird tatsächlich gesendet? – zipzit

+0

Es ist unwahrscheinlich. UDP liefert die vollständige Nachricht oder nichts. Es ist die einzige Garantie, die UDP macht. Wenn also das, was Sie sagen, wahr ist, ist in Ihrer Netzwerkinfrastruktur, Ihrem Betriebssystem oder im Code-Compiler etwas kaputt. – jgauffin

+0

@zipzit Wenn du durch wireshark meinst, ja, der ganze Inhalt zeigt sich. Die fraglichen Daten sind binäre Handshake-Pakete, die Teil des RakNet-Protokolls sind. – jython234

Antwort

3

Problem mit dieser Linie ist:

bool recv(ref Address address, ref byte[] buffer) 

Mit ref Sie nicht in Scheiben schneiden, aber Sie wirklich original Puffer so ändern, wenn vorherige Paket ist 7 Bytes lang, als Sie nicht mehr empfangen können als 7 Bytes mehr

So können Sie Ihren Code ref entfernen ändern und Länge zurück, anstatt schlicht Bool

size_t recv(ref Address address, byte[] buffer); 

und dann:

Address a; 
byte[] data = new byte[1024 * 1024]; 
size_t len; 
while(max-- > 0 && (len = socket.recv(a, data))) { 
    handlePacket(a, data[0 .. len]); 
} 

Aber das wird wahrscheinlich mit Ihrer handlePacket Funktion nicht funktionieren, weil eine andere ref so eine weitere Variante Ihre recv tun nicht ändern, sondern nur einen Teil des Codes arount handlePacket

Address a; 
byte[] data = new byte[1024 * 1024]; 
size_t arr = data[]; 
while(max-- > 0 && socket.recv(a, arr)) { 
    handlePacket(a, arr); 
    arr = data[]; 
} 
+0

Er kann nicht einfach die ref entfernen, weil er die aktualisierte '.length' für' handlePacket' benötigt. Aber ein Problem ist in der Tat, dass nach dem ersten Recv-Aufruf der an "receiveFrom" übergebene "Datenpuffer" zu klein ist. Mögliche Lösungen: Entfernen Sie das 'ref', aber geben Sie das aktualisierte Segment von' recv' zurück und verwenden Sie dieses für 'handlePacket'. Oder halten 'recv' unmodified und setzen' data' auf die komplette Puffergröße nach 'handlePacket' zurück. – jpf

+0

@jpf Ja, ich habe meine Antwort geändert, um sie genauer zu machen – Kozzi11

+0

Könnten Sie tiefer gehen, warum 'ref byte [] buffer' nur 7 Bytes akzeptiert? Das ergibt für mich keinen Sinn. –