# CRC geprüfte UDP Pakete..



## Kalkulon (19. Apr 2010)

Hallo, habe ein Problem. Wenn ich den CRC Wert des Inhaltes eines UDP Paketes berechne danach das Paket verschicke und nochmals den CRC Wert des Inhalts berechne kommt ein anderer Wert raus! Was mache ich falsch?


```
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.zip.CRC32;


public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws IOException {
		DatagramSocket socket = new DatagramSocket(5008);
		
		byte[] data = "zu verschickende Daten....".getBytes();
		
		CRC32 crc = new CRC32();
		crc.update(data);
		System.out.println(crc.getValue());
		DatagramPacket packet = new DatagramPacket(data, data.length);
		packet.setPort(5008);
		packet.setAddress(InetAddress.getByName("localhost"));
		socket.send(packet);
		byte[] buf = new byte[508];
		DatagramPacket packetIn = new DatagramPacket(buf, 508);
		socket.receive(packetIn);
		
		byte[] test = packetIn.getData();
		
		crc.reset();
		crc.update(test);
		
		System.out.println(crc.getValue());
	}
	

}
```

Etwas habe ich schon rausgefunden, wenn ich genau weiß wie groß der Inhalt des Paketes ist und ich nur genau die Größe angebe beim Empfangen des Paketes klappt es mit der Berechnung des CRC's. Was mache ich aber, wenn ich nicht genau weiß wie groß das Paket ist?


----------



## SlaterB (19. Apr 2010)

vergleiche doch die beiden Arrays


----------



## Kalkulon (19. Apr 2010)

geht leider nicht, weil ich die Daten verschicken muss und der Empfänger keinen Zugriff auf die Daten des Senders hat!


----------



## SlaterB (19. Apr 2010)

ich meine in deinem Testprogramm, schau dir deine beiden Arrays an, dann könnte dir der Fehler sofort auffallen,
wenn du CRC auf unterschiedlichen Arrays ausführst kannst du das dem nicht anlasten


----------



## Kalkulon (19. Apr 2010)

leider nicht!


----------



## SlaterB (19. Apr 2010)

was heißt leider nicht?
na gut, ich verrate es dir, schon die grundlegendste Eigenschaft ist anders: die Arrays sind nicht gleich lang

wieso sind eigentlich beim Empfänger genau 508 Bytes vorgesehen, das sieht ja sehr speziell aus,
dann kannst du auch gleich den passenden 508er String beim Empfänger in der Quellcode schreiben


----------



## Kalkulon (19. Apr 2010)

wenn ich aber weiß wie groß der Content ist klappt es ja mit dem CRC!


```
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.zip.CRC32;


public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws IOException {
		DatagramSocket socket = new DatagramSocket(5008);
		
		byte[] data = "zu verschickende Daten....".getBytes();
		
		CRC32 crc = new CRC32();
		crc.update(data);
		System.out.println(crc.getValue());
		DatagramPacket packet = new DatagramPacket(data, data.length);
		packet.setPort(5008);
		packet.setAddress(InetAddress.getByName("localhost"));
		socket.send(packet);
		byte[] buf = new byte[508];
		DatagramPacket packetIn = new DatagramPacket(buf, 508);
		socket.receive(packetIn);
		packetIn.getData();
		crc.reset();
		crc.update(buf,0,26);
		System.out.println(crc.getValue());
	}
}
```


----------



## SlaterB (19. Apr 2010)

genau, du musst erst wissen, wie groß der Content ist, sonst klappt CRC nicht,
das ist kein Problem sondern eine wichtige Grundlage

56
hat eine andere Prüfsumme als
560
oder
5600
oder 
56000000000000000000000000

du kannst nicht beliebig 0en ranhängen und erwarten dass sie ignoriert werden,
bei einfachen Verfahren wie Quersumme in der Mathematik mag das der Fall sein, hier aber anscheinend nicht,
und allgemein ist das doch eine wichtige Information, stell dir vor das wär ein Geldbetrag 

unabhängig von CRC musst du erstmal über UDP das Original-byte-Array wiederherstellen, vorher geht gar nix


----------



## Kalkulon (19. Apr 2010)

ok danke! also muss ich die Größe des Contents übermitteln und auf dieser Basis dann die CRC Prüfung machen.


----------



## SlaterB (19. Apr 2010)

scheint fast so, obwohl doch der Socket wissen sollte, wie viele bytes ankommen..
aber ich weiß da nix genaueres, die DatagramPacket-Konstruktoren sagen nicht viel mehr aus,

vielleicht weiß es noch wer anders oder Tutorials zum Thema mit Beispielen

nach
Writing a Datagram Client and Server (The Java™ Tutorials > Custom Networking > All About Datagrams)
z.B.
getLength() von DatagramPacket...


----------



## tuxedo (21. Apr 2010)

Ich denke es ist noch ein wenig komplexer:

UDP Pakete können unterwegs fragmentiert werden. D.h. es ist nicht gesagt dass wenn du 508 bytes in einem Paket abschickst, du auf empfängerseite auch die 508 bytes am Stück bekommst. Eventuell kommen mit dem ersten lesen nur 400 bytes an. Dann hast du zwar schonmal die größe, musst aber schauen dass du die noch fehlenden 108 bytes kriegst.

Theoretisch wird's sogar noch komplexer:
Wenn zwei 508 bytes Pakete fragmentiert werden:

Paket A_0 = 400 bytes
Paket A_1 = 108 bytes
Paket B_0 = 300 bytes
Paket B_1 = 208 bytes

Da die Reihenfolge der empfangenen Pakete beliebig sein kann, könnte die Empfangsreihenfolge so aussehen:

A_0
B_1
B_0
A_1

Viel Spass beim zusammensetzen ;-) Wobei ich mir bei dieser Aussage nicht 100%ig sicher bin ob das technsich vollständig korrekt ist.. Aber immerhion bin ich mir 90%ig sicher.
Solltest da jedenfalls nochmal ein wenig recherchieren bevor du alles festzurrst.

- Alex


----------



## Empire Phoenix (21. Apr 2010)

Wozu der blödsinn ?
Udp hat inner implementation bereits einen CRC algoritmus drinne, fehlerhafte packet werden schlichtweg gedroppt. Kannst dir also eine eigene Feherüberprüfung sparen, wenns ankommt ist die checksum korrekt
Fragmentierung bin ich nciht hunderprozentig sicher, aber bisslang war übers internet 2-3k packete kein problem mit fragmentierung, ein kurzer check bei google hat mitr aber gerade gesagt das das reassembling im ip protokoll bereits gemacht wird, daher sollte das auch egal sein.


----------



## tuxedo (21. Apr 2010)

Hmm, wie ist das denn mit Fragmenten? Wenn da eins von 2 Fragmenten eines einzelnen Pakets verloren geht: Wird dann das zweite Fragment mit gedroppt?

- Alex


----------



## Empire Phoenix (22. Apr 2010)

Jep, bereits auf unteren ebenen so wie es aussieht weil das reassemblen dann scheitert.

--------------------------

Btw für dich als TCP liebhaber bei spielen mal dazugepackt.
Nutzlast 400byte,
-> Overhead duch Ethernet layer + IpLayer + Tcp layer = 5xx byte
-> weniger als 50% effizienz
Udp 
400byte nutzlast
-> overhad durch ip  (160) + Etherent (160) + Udp(20) + short zur flusskontrolle(2byte)  = 342 byte
-> rund 200 byte gesparrt
Bei kleineren Packeten wird das sogar noch schlimmer, und updates von positionen sind nicht gerade groß.


----------



## tuxedo (22. Apr 2010)

Empire Phoenix hat gesagt.:


> Jep, bereits auf unteren ebenen so wie es aussieht weil das reassemblen dann scheitert.



Ah, wusste nicht dass UDP die Fragmente selbst wieder zusammensetzt. Danke für die Info.




> Btw für dich als TCP liebhaber bei spielen mal dazugepackt.



Ich bin kein "TCP Liebhaber bei Spielen". Ich sag nur man sollte wissen wo die einzelnen Stärken und Schwächen liegen.




> Nutzlast 400byte,
> -> Overhead duch Ethernet layer + IpLayer + Tcp layer = 5xx byte
> -> weniger als 50% effizienz
> Udp
> ...



Deine Rechnung kann ich so nicht ganz unterschreiben.

Hier wird TCP mit UDP vergleichen



			
				http://sd.wareonearth.com/~phil/net/overhead/ hat gesagt.:
			
		

> TCP over Ethernet:
> Assuming no header compression (e.g. not PPP)
> Add 20 IPv4 header or 40 IPv6 header (no options)
> * Add 20 TCP header*
> ...




geht man bei beiden von IPv4 aus und nimmt man beiden den Best-Case, dann steht TCP mit 94.9285 % gegenüber 95.7087 % von UDP. Die Differenz beträgt 0,7% ... Ich denke das veranschaulicht meine bisherigen Statements recht gut ...


----------

