# UDP Fehlerbehandlung



## spitzname (30. Okt 2010)

Hallo, unten habe ich Codes für Anwendung der Clientseite und der Serverseite aufgeschrieben. Leider habe ich schwierigkeiten meine Ideen zu Fehlerbehandlung bei UDP Datenübertragung in Java Code umzustezen und würde mich über Tipps freuen.

Folgende Fehler sollen behandelt werden:
-Paketverlust
-Falsche Datenübertragung

Zeit Messen:
-Transferzeit messen

mein Ansatz zu Paketverlust:
Das erste bit des Pakets wird für die Sequenznummer reserviert, diese wird dann mit dem
Paket mitgeschickt. Erst wenn die Sequenznummer auf der Sender- und
Empfängerseite übereinstimmt, kann ein weiteres Paket verschickt werden, sonst
soll das erste Paket nochmal verschickt werden.

Bitfehlerrate:
Die CRC-Werte werden auf der Sender und Empfänger Seite ausgerechnet und
miteinander verglichen. Wenn beide Werte übereinstimmen, dann ist der
Rahmen unverfälscht angekommen.

Transferzeit:
Um die Transferzeit zu messen, wird vor dem Absenden des Rahmens ein Timer
gesetzt, der die aktuelle Zeit speichert. Beim erfolgreichen Ankommen des
Rahmens speichert der zweite Timer die aktuelle Zeit. Die Differenz der beiden
Zeiten ist dann die Transferzeit des gesendeten Rahmens.

Server

```
public class FileTransferServer {


    public static void main(String args[]) throws Exception{
        // Arguments: port & filename
        int s = 12345;
        String filename = "sink.txt";
	    // Open datagramm socket
	    javax.net.DatagramSocket dtgSock;
        dtgSock = new javax.net.DatagramSocket(s);

        byte[] buf = new byte[5000];
	    java.io.FileOutputStream fw = new java.io.FileOutputStream(filename);
	    DatagramPacket packet = new DatagramPacket(buf, buf.length);
      

	    while (true){
                
		    dtgSock.receive(packet);
		    System.out.print("*");
             
                    // if receive an empty packet will indicate end of file
		    if (packet.getLength()==0) break;
   
            fw.write(packet.getData(),0,packet.getLength());		

	    }

	fw.flush();
	fw.close();
        
	dtgSock.close();	// Close the Socket
        
    }
}
```


Client

```
import java.net.*; // we use Sockets
import java.util.zip.*;

public class FileTransferClient {


    public static void main(String args[]) throws Exception{
   
        String srvName = "localhost";
        int srvPort = 12345;
        String filename = "source.txt";

	    // Open datagramm socket
	    javax.net.DatagramSocket dtgSock;
        dtgSock = new javax.net.DatagramSocket();
        InetSocketAddress srvSockAddr = new InetSocketAddress(srvName, srvPort);
        dtgSock.connect(srvSockAddr);

        byte[] buf = new byte[5];

	    java.io.FileInputStream fr = new java.io.FileInputStream(filename);

	    int len; // number of bytes written from the file

	    while ((len=fr.read(buf,0,buf.length))!= -1){

	        DatagramPacket packet = new DatagramPacket(buf, len);              
        	dtgSock.send(packet);
	        System.out.print("*");
            Thread.sleep(100);
         
	    }

	// Send an empty packet to the server to indicate end of file
        DatagramPacket packet = new DatagramPacket(buf, 0);
       	dtgSock.send(packet);
        
	 
        dtgSock.close();	// Close the Socket

    }
}
```

Danke im voraus

Gruß


----------



## ice-breaker (30. Okt 2010)

spitzname hat gesagt.:


> -Paketverlust


warum verwendest du dann nicht TCP? Schau dir mal an wie TCP die Zuverlässigkeit sicherstellt, das ist ziemlich intelligent gemacht.



spitzname hat gesagt.:


> -Falsche Datenübertragung


das kannst du nicht erkennen, falsche UDP-Pakete werden automatisch gelöscht, UDP hat nämlich selbst schon eine Prüfsumme, du wirst also nie ein falsches Paket in deiner Anwendung bekommen.


----------



## spitzname (30. Okt 2010)

Erstmal danke für die Antwort, es muss leider erstmal UDP sein, da ich dieses Thema verstehen will bevor ich zu TCP wechsle, dieses Thema kommt auch noch dran.

Es wird Simuliert, dass die Bitübertragungsschicht Rahmen verfälscht werden und dafür soll eine Lösung gefunden werden.

Würde mich weiterhin über Tipps freuen.

Lg


----------



## HoaX (30. Okt 2010)

spitzname hat gesagt.:


> Transferzeit:
> Um die Transferzeit zu messen, wird vor dem Absenden des Rahmens ein Timer
> gesetzt, der die aktuelle Zeit speichert. Beim erfolgreichen Ankommen des
> Rahmens speichert der zweite Timer die aktuelle Zeit. Die Differenz der beiden
> Zeiten ist dann die Transferzeit des gesendeten Rahmens.



Wirst du so nicht hinbekommen, denn welche zwei Uhren laufen schon synchron?


----------



## spitzname (30. Okt 2010)

HoaX hat gesagt.:


> Wirst du so nicht hinbekommen, denn welche zwei Uhren laufen schon synchron?


Ok da ist was dran, dann muss ich mir was anderes überlegen. 


Ist mein Ansatz zu Fehlerbehandlung sonst Umsetzbar?:bahnhof:

Lg


----------



## ice-breaker (31. Okt 2010)

spitzname hat gesagt.:


> Ok da ist was dran, dann muss ich mir was anderes überlegen.


mach es wie das Ping-Kommando.
Sende 1 Paket zu der Gegenseite, dieser muss wieder antworten. Die Zeit für 1 Paket ist dann ~ Gesamtzeit/2




spitzname hat gesagt.:


> Ist mein Ansatz zu Fehlerbehandlung sonst Umsetzbar?:bahnhof:


natürlich kannst du eine Sicherungsschicht (garantierte Übertragung) auf UDP bauen.


----------



## spitzname (31. Okt 2010)

ice-breaker hat gesagt.:


> mach es wie das Ping-Kommando.
> Sende 1 Paket zu der Gegenseite, dieser muss wieder antworten. Die Zeit für 1 Paket ist dann ~ Gesamtzeit/2
> 
> danke für den Tipp.
> ...



Ok, also um den Paketverlust zuvermeiden fügt man jedem versendeten Paket eine Sequenznummer hinzu.
Das erste bit des Pakets wird für die Sequenznummer reserviert, diese wird dann mit dem
Paket mitgeschickt. Erst wenn die Sequenznummer auf der Sender- und
Empfängerseite übereinstimmt, kann ein weiteres Paket verschickt werden, sonst
soll das erste Paket nochmal verschickt werden.

Also so: Im Clientcode im Main :

```
while ((len=fr.read(buf,1,buf.length-1)+1)!= -1){
 
            
            DatagramPacket packet = new DatagramPacket(buf, len);
            //die Sequenznr. wird am Anfang des Rahmens eingefügt
            buf[0] = ++paketzaehler[0]; 
            //Paket wird versendet
            dtgSock.send(packet);
            Thread.sleep(100);

             //auf eine Antwort warten
            try{
            dtgSock.setSoTimeout(500); //Timeout setzen 
            DatagramPacket recievepacket = new DatagramPacket(ack, ack.length);
            dtgSock.receive(recievepacket);     // blocking!!!         
            
            }  catch(java.io.InterruptedIOException ex){
               continue; //wenn der Timeout abgelaufen, dann noch mal senden
               }
         
        }
```

Server

```
while (true){
             // if receive an empty packet will indicate end of file
            if (packet.getLength()==0) break;
            ++paketzaehler[0];
            dtgSock.setSoTimeout(0);
            dtgSock.receive(packet);
            if(buf[0] == paketzaehler[0]){
            i++;
            System.out.print("\nEs wurden soviele Pakete empfangen: "+ i);
            fw.write(packet.getData(),1,packet.getLength()-1);
            DatagramPacket rpacket = new DatagramPacket(antw, antw.length);
            dtgSock.send(rpacket);
            } else breack;   
 
        }
```


Das Programm funktioniert aber leider nicht wie gewünscht wo liegt mein Fehler, würde mich über Tipps freuen.

Lg


----------

