Pfadangabe Datei senden

Admiral Helmut

Aktives Mitglied
Hallo liebe Leut, Experten 😉

ich hänge seit einiger Zeit an einem Problem, vielleicht könnt ihr mir helfen.

ich möchte eine Datei sicher versenden. Es geht dabei um Netzwerk Protokol Kram. dass heisst UDP etwas sicherer machen mit Checksumme etc. Diesen Teil habe ich aber eigentlich verstanden.
Es geht mehr um java Grundlagen zu Pfadangabe (deswegen dieses Forum)

Ich verwende dazu folgenden Code. Über die Console kann man den Dateinamen, ZielIP und Port angeben.
Leider bekomme ich immer nur Exceptions bzw die Fehlermeldung "Lost Package" wegen dem SOcket TimeOut. Ich denke es liegt daran dass er die Datei nicht findet. Ich habe schon einiges an schreibweisen ausprobiert. Vielleicht weiss einer was ich eingeben muss.

(das mit der Checksumme usw könnt ihr getrost weglassen.) es nur darum dass ich mal eine datei verschicken kann.

Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.util.Scanner;
import java.util.zip.Adler32;

public class FileSender
{
	
	public static void main(String[] args)
	{
		Scanner in = new Scanner(System.in);  // Eingabe für FileName
		System.out.print("Enter Filename: ");
		String input = in.next();	//Filename
		File file = new File(input);
		System.out.print("Enter Ziel IP: ");
		String remote = in.next();		//IP Adresse
		System.out.print("Enter Ziel Port: ");
		int port = in.nextInt();	//Zielport
		
		
		sendFile(file, remote, port);
	}

	private static void sendFile(File file, String address, int port)		//File laden und versenden
	{
		byte ackAlt = 0;
		
		byte[] ackNeu = {0};
		byte[] sendBytes = new byte[1400];
		
		try
		{
			FileInputStream input = new FileInputStream(file);		//File holen
			String filepath = file.getName();
			String filename = filepath.substring(filepath.lastIndexOf("\\")+1);
			byte[] tmp = filename.getBytes();
			byte[] filenameBytes = new byte[1400];
			System.arraycopy(tmp, 0, filenameBytes, 0, tmp.length);
			filenameBytes[filenameBytes.length -1] = 2;
			byte[] check = calculateChecksum(filenameBytes);
			System.arraycopy(check, 0, filenameBytes, 1380, check.length);
			filenameBytes[filenameBytes.length -2] = (byte) check.length;
			
			DatagramSocket socket = new DatagramSocket(9010);
			
			socket.setSoTimeout(10000);
			
			DatagramPacket sendPacket = new DatagramPacket(filenameBytes, filenameBytes.length, InetAddress.getByName(address), port);
			DatagramPacket received = new DatagramPacket(ackNeu, 1, InetAddress.getByName(address), 9010);
			
			while(true)
			{
				if(ackAlt != ackNeu[0] && input.available() > 0)
				{
					try
					{
						sendBytes = new byte[1400];
						tmp = new byte[1380];
						
						input.read(tmp);
						System.arraycopy(tmp, 0, sendBytes, 0, tmp.length);
						
						sendBytes[sendBytes.length -1] = ackAlt;
						
						check = calculateChecksum(sendBytes);  //berechne Checksumme unten Adler32
						
						System.arraycopy(check, 0, sendBytes, 1380, check.length);
						sendBytes[sendBytes.length -2] = (byte) check.length;
						
						sendPacket = new DatagramPacket(sendBytes, sendBytes.length, InetAddress.getByName(address), port);
						if(ackNeu[0] == 2)
							ackNeu[0] = 1;
						ackAlt = ackNeu[0];
					}
					catch(IOException ioex)
					{
						;
					}
					socket.send(sendPacket);
				}
				try
				{
					socket.receive(received);
					ackNeu = received.getData();
					
					if(input.available() <= 0)
					{
						sendBytes[sendBytes.length -1] = 3;
						sendPacket = new DatagramPacket(sendBytes, sendBytes.length, InetAddress.getByName(address), port);
						
						socket.send(sendPacket);
					}
					if(ackNeu[0] == 3 && input.available() <= 0)
					{
						break;
					}
				}
				catch(SocketTimeoutException timeoutEx)
				{
					if(ackNeu[0] == 3 && input.available() <= 0)
					{
						break;
					}
					System.out.println("Lost package.");
					socket.send(sendPacket);
					continue;
				}
				catch(IOException ex)
				{
					if(ackNeu[0] == 3 && input.available() <= 0)
					{
						break;
					}
				}
			}
		}
		catch(IOException e)
		{
			
		}
	}

	private static byte[] calculateChecksum(byte[] bytes)	//Checksumme berechnen
	{
		Adler32 adler = new Adler32();	// Klasse zum berechnen der Checksumme nach Mark Adler, gilt für 32 bit Zahlen
		adler.reset();
		adler.update(bytes);
		ByteBuffer bb = ByteBuffer.allocate(8);
		return bb.putLong(adler.getValue()).array();
	}

}

es gibt noch ein Programm FileReceiver das bei mir auf dem gleichen Rechner läuft, also adressiere ich 127.0.0.1 und den passenden Port.
der Receiver macht grob nur in einer while schleife:

Java:
socket.receive(receivedPacket);

				received = receivedPacket.getData();

				fileBytes = new byte[received.length -20];

Vielen herzlichen Dank für eure Hilfe
Ich wäre euch super dankbar wenn einer eine Idee hätte

gruß Helmut
 
Wenn mich nicht alles täuscht übergibst du zwar ein File Objekt aber initialisierst es nicht

Java:
 private static void sendFile(File file, String address, int port)       //File laden und versenden
    {
        byte ackAlt = 0;
        
        byte[] ackNeu = {0};
        byte[] sendBytes = new byte[1400];
        
        try
        {
            FileInputStream input = new FileInputStream(file);      //File holen
            String filepath = file.getName();

ich bin der meinung hier fehlt sowas :

Java:
File myFile = new File(file);

   FileInputStream input = new FileInputStream(myFile);

[EDIT]Seh grad das machst du in der main , mein Fehler 🙂[/EDIT]

Aber hast du es mal gedebuggt ? und mal geschaut was genau dein File Objekt (file) an dieser Stelle referenziert ?

Java:
            FileInputStream input = new FileInputStream(file);

oder einfach mal per sysout ausgeben lassen ?
 
Zuletzt bearbeitet:
Ersteinmal vielen Dank für deine Mühe.

ok ich probiere es mal so:
System.out.println(file);

ist das richtig:

Wenn ich eine datei z.B. helmut.txt in den gleichen ordner tue wie die .java datei, dann gebe ich in der console als pfad einfach helmut.txt ein?

gruß helmut
 
als Ausgabe erhalte ich dann helmut.txt
genauso wie bei der testausgabe des filepath 2 zeilen drunter (ist auch schon im code oben)

allerdings erhalte ich wieder eine file not found exception obwohl meine datei helmut.txt sowohl im projektordner ist als auch im src ordner.


also liegt es wohl nur an der pfad angabe aber ich habe keinerlei idee was ich schreiben soll.

PS: es ist egal wo die datei später liegt, hauptsache das programm findet sie

gruß helmut

nochmal danke für dein Bemühen
 
Pfadangaben immer mit vollem Dateipfad angeben

sprich C:/Dokumente und Einstellungen/usw...

dann sollte das eigentlich klappen 😉
 
Zuletzt bearbeitet:
Hallo kaoZ

Vielen Dank für deine Hilfe.
Durch dich hab ich zumindest festgestellt dass ich total auf dem falschen Weg war 🙂 🙁🙁🙁 entschuldigung

das Problem liegt wohl am FileReceiver
Java:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.util.Scanner;
import java.util.zip.Adler32;

public class FileReceiver
{

	public static void main(String[] args) throws FileNotFoundException, IOException
	{
		Scanner in = new Scanner(System.in);
		System.out.print("Enter port: ");
		int port = in.nextInt();

		FileOutputStream fileOut = null;
		byte ackOld = 3;

		byte[] ackNew = {3};

		byte[] received = new byte[1400];
		byte[] fileBytes;

		DatagramPacket ack = null;
		DatagramSocket socket = new DatagramSocket(port);

		socket.setSoTimeout(1000);

		DatagramPacket receivedPacket = new DatagramPacket(received, 1400);

		int count = 0;
		System.out.println("Accepting packets..");
		while(true)
		{
			try
			{
				socket.receive(receivedPacket);
				System.out.println("da kommt was");

				received = receivedPacket.getData();

				fileBytes = new byte[received.length -20];

				byte checkLength = received[received.length -2];
				byte[] check = new byte[checkLength];
				System.arraycopy(received, 1380, check, 0, checkLength);

				for(int i = 1380; i< 1399; i++)
				{
					received[i] = 0;
				}

				ackNew[0] = received[received.length -1];
				if(checkCheckSum(check, received) || ackNew[0] == 3)
				{
					System.arraycopy(received, 0, fileBytes, 0, fileBytes.length);

					if(ackNew[0] == 2)
						//fileOut = new FileOutputStream(new String(fileBytes));
						fileOut = new FileOutputStream("helmi.txt");
					else if(ackNew[0] != 3 && ackNew[0] != ackOld)
					{
						System.out.println("Packet received.");
						count++;
						fileOut.write(fileBytes);
					}
					else if(ackNew[0] == 3 && ackNew[0] != ackOld)
					{
						fileOut.close();
						System.out.println("File successfully received");
						System.out.println("Received a total of " + count + " packets.");


					}
					SocketAddress addr = receivedPacket.getSocketAddress();

					ack = new DatagramPacket(ackNew, 1, addr);

					socket.send(ack);
					ackOld = ackNew[0];
				}
			}
			catch(SocketTimeoutException timeoutEx)
			{
				continue;
			}
		}
	}
	private static boolean checkCheckSum(byte[] receivedCheck, byte[] received)
	{
		byte[] newChk = calcChecksum(received);
		if (newChk.length == receivedCheck.length)
		{
			for (int i = 0; i < newChk.length; i++)
			{
				if (newChk[i] != receivedCheck[i])
				{
					System.out.println("Found a bit error");
					return false;
				}
			}
		}
		return true;
	}

	private static byte[] calcChecksum(byte[] b)
	{
		Adler32 ad = new Adler32();
		ad.reset();
		ad.update(b);
		ByteBuffer bb = ByteBuffer.allocate(8);
		return bb.putLong(ad.getValue()).array();
	}
}

in der while schleife ca mitte siehst du bei if(acknew[0]==2)
eine auskommentierte Zeile. diese hat zu dem fehler geführt. meine neue Zeile führt nun dazu dass die datei ankommt. leider bekomm ich nun bitfehler weil die netzwerksache wohl noch nicht so funktioniert. weiss leider nicht wieso

gruß Helmut
 
versuch mal folgendes , der outputstream erwartet ja ein File und keinen String

und denk daran den kompletten Pfad anzugeben 😉

Java:
 fileOut = new FileOutputStream("helmi.txt");

Java:
fileOut = new FileOutputStream(new File("C:/usw.usw"));

poste mal den dazugehörigen stackTrace / und die Fehlermeldung

[EDIT]
Hat es eigentlich einen besonderen Grund warum du einen FileOutputStream nutzt anstelle eines BufferedWriter/Readers ? Ich nutze den FileOutputStream immer nur in Verbindung mit einem ObjectOutputStream wenn ich serialisiert Daten schreiben möchte.

Ich kenne das eigentlich nur so das man Daten/Objekte sowieso nur serialisiert durch Netzwerke schickt.

[/EDIT]
 
Zuletzt bearbeitet:
Jo das Klappt.
ging auch mit meiner Version.

Danke

Das Problem ist, dass in der Logik noch was falsch ist und die Checksumme nicht gleich ist.
Deswegen gibt mein Programm Bitfehler aus.

Das komische:

Die neue Datei hat den gleichen Inhalt.
die Größe in den Eigenschaften ist doppelt so groß
die Größe auf dem Datenträger (auch in den Eigenschaften) ist gleich.
 
als konsolen ausgabe erhalte ich das hier:


Enter port: 4000
Accepting packets..
da kommt was
da kommt was
Packet received.
da kommt was
Found a bit error
File successfully received
Received a total of 1 packets.
da kommt was
Found a bit error
 
Die checksumm ist soweit ich weiß nur komplett identisch insofern es genau das gleiche Objekt ist , zumindest habe ich da flüchtig mal was gelesen , bin ich mir zumindest ziemlich sicher, da du aber ein neues Objekt (File) erstellst kann meines wissens nach die checksumme nicht die gleiche sein, glaub ich zumindest :rtfm:

kannst du den StackTrace zu dem Bitfehler posten ? dann könnte man ggf. den Fehler eingrenzen

pack das ganze mal in einen Try/Catch Block
 
Zuletzt bearbeitet:
also es ist so:

das ist eine Aufgabe aus meinem Studium.
dabei geht es hauptsächlich im den Netzwerkvorgang also UDP sicher zu machen.

Dazu haben wir beispiel codestücke bekommen die wir einsetzen würfen, da java kenntnisse nicht das wichtigste in diesem fall sind.

und das mit dem Fileoutputstream ist nicht von mir.
aber kann ich mit reader writer auch nicht txt- dateien erstellen?
 
dann wird der fehler wohl daran liegen dass ich ein neues erstelle anstatt wie die auskommentierte das byte Array mitnehme.

allerdings verstehe ich nicht wie das mit dem Bytearray funktionieren soll. und es funktioniert ja auch nicht....

Vielen herzlichen Dank für dein Bemühen
 
ByteArrayOutputStream / inputStream schonmal versucht ?

was genau willst du machen ? du möchtest eine Datei über das Netzwerk senden , richtig ? wozu dient das ByteArray? für die Checksumme ?


zum StackTrace (gibt die Fehlermeldung in der Console aus | Exception Handling):

Java:
try{

    // dein outputStream code usw...

}catch(Exception ex){
    ex.printStackTrace();
}
 
Zuletzt bearbeitet:
vielen Dank

Alles richtig was du gesagt hast.

nur habe ich keine Exceptions.

das sind "Fehlerausgaben" meines Programms

die sagen mir nur dass die Checksumme nicht die gleiche ist.

sonst läuft das Programm durch ohne Exceptions
 

Zurück
Oben