Datei mittels TCP übertragen

Guten Tag
ich bin kein so großer Java-kenner, desswegen stelle ich diese Fragen.

Zu Frage 1 und 2: Ich finde im Quelltext nirgends die Stelle in der die IP und der Port definiert sind. Die Zeile wo steht this.port = port sagt mir da nicht viel. Wenn ich das Programm laufen lassen will, versucht er immer auf den localhost zuzugreifen und immer auf einen bestimmten Port.
Zu Frage 3 und 4: Ich möchte, dass der Server wählt (indemfall mein rechner), welche datei er verschickt. Er soll sie dann bei einem anderen Rechner in einen bestimmten Ordner legen.

Ich fände es echt nett, wenn ihr mir noch weiterhelfen könnt. Wie gesagt, in Java kenne ich nur die grundkenntnisse und verstehe nicht sehr viel von Netzwerkprogrammierung

gruß
EGJ-Soldier

Also zunächst mal wäre es sicher von Vorteil für Dich tiefer als bisher in Java einzusteigen.
Du hast im Grunde schon die richtige Zeile bezüglich Port rausgefunden. this.port=port bedeutet überweise der Member-Variable port den inhalt von der lokale Variable (in diesem Fall Parameter) port. Wenn Du gerade mal eine Zeile darüber schaust siehst Du dass dort die Member-Variable port definiert ist.

Zum Thema 3 & 4 ist im Gunde nur Phantasie gefragt. Man könnte der Einfachheit wegen z.B. alles hard codeieren, dass der Server fest den Dateinamen in sich integriert hat, und das Ziel wohin dem Client überlassen wird, was ebenfalls der Einfacheit halber hart codiert werden könnte. Wenn Du es ein bissel weicher haben willst würde ich empfehlen diese Kerninformationen (Quelldateiname auf Seiten des Servers, und Zieldateipfad auf Seiten des Clients in jeweilige Properties-Dateien zu speichern und bei Bedarf zu lesen.
Bitte erwarte hier keinen Code von mir, es wäre Dir mehr von Nutzen Dir selbst detailiertere Gedanken zu machen und Dich dadurch auch in Sachen Java sicherer zu machen.

viel Spaß

Takidoso
 
Zuletzt bearbeitet:
Ich bedanke mich für deine hilfe und werde mir deinen rat zu Herzen nehmen
(Ich werde mich was tiefer mit Java beschäftigen)

Gruß
EGJ-Soldier
 
Hallo,

hier mal noch nachträglich eine etwas schneller NIO Variante:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author Tom
 * 
 */
public class TCPFileExchange {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		File file = new File("D:/VMWare/40g xp development/xp-s005.vmdk");
		FileProvider fileProvider = new FileProvider(file, 4711);

		FileFetcher fileFetcher = new FileFetcher("localhost", 4711);
		ExecutorService executorService = Executors.newFixedThreadPool(2);
		executorService.execute(fileProvider);
		executorService.execute(fileFetcher);

		executorService.shutdown();
	}

	static class FileProvider implements Runnable {

		final File file;

		final int port;

		public FileProvider(File file, int port) {
			this.file = file;
			this.port = port;
		}

		public void run() {
			try {
				System.out.println(getClass() + " Providing file...");

				ServerSocketChannel serverSocketChannel = ServerSocketChannel
						.open();
				serverSocketChannel.socket().bind(new InetSocketAddress(port));
				SocketChannel socketChannel = serverSocketChannel.accept();
				Socket socket = socketChannel.socket();

				FileInputStream fileInputStream = new FileInputStream(this.file);
				DataOutputStream dataOutputStream = new DataOutputStream(socket
						.getOutputStream());
				dataOutputStream.writeUTF(file.getName());
				dataOutputStream.writeLong(file.length());

				dataOutputStream.flush();

				FileChannel fileChannel = fileInputStream.getChannel();

				transfer(fileChannel, socketChannel, file.length(),
						1024 * 1024 * 16, true, true);

				fileInputStream.close();

				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	static class FileFetcher implements Runnable {

		String serverName;

		int port;

		public FileFetcher(String serverName, int port) {
			this.serverName = serverName;
			this.port = port;
		}

		public void run() {
			try {
				SocketChannel socketChannel = SocketChannel
						.open(new InetSocketAddress(serverName, port));
				Socket socket = socketChannel.socket();

				DataInputStream dataInputStream = new DataInputStream(socket
						.getInputStream());
				String fileName = dataInputStream.readUTF();
				long sizeInBytes = dataInputStream.readLong();

				System.out.println("FileSize: " + sizeInBytes);

				File file = new File("c:/temp", "x_" + fileName);
				System.out.println(getClass() + " Fetching file... " + file);
				FileOutputStream fileOutputStream = new FileOutputStream(file);
				FileChannel fileChannel = fileOutputStream.getChannel();

				transfer(fileChannel, socketChannel, sizeInBytes,
						1024 * 1024 * 16, true, false);

				fileOutputStream.close();
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void transfer(FileChannel fileChannel,
			SocketChannel socketChannel, long lengthInBytes,
			long chunckSizeInBytes, boolean verbose, boolean fromFileToSocket)
			throws IOException {

		long overallBytesTransfered = 0L;
		long time = -System.currentTimeMillis();
		while (overallBytesTransfered < lengthInBytes) {

			long bytesTransfered = 0L;

			if (fromFileToSocket) {
			  bytesTransfered = fileChannel.transferTo(overallBytesTransfered, Math.min(
                        chunckSizeInBytes, lengthInBytes
                                - overallBytesTransfered), socketChannel);
			} else {
				bytesTransfered = fileChannel.transferFrom(socketChannel,
						overallBytesTransfered, Math.min(chunckSizeInBytes,
								lengthInBytes - overallBytesTransfered));
			}

			overallBytesTransfered += bytesTransfered;

			if (verbose) {
				System.out.printf(
						"overall bytes transfered: %s progress %s%%\n",
						overallBytesTransfered, Math
								.round(overallBytesTransfered
										/ ((double) lengthInBytes) * 100.0));
			}

		}
		time += System.currentTimeMillis();

		if (verbose) {
			System.out.printf("Transfered: %s bytes in: %s s -> %s kbytes/s",
					overallBytesTransfered, time / 1000,
					(overallBytesTransfered / 1024.0) / (time / 1000.0));
		}

	}

}

Code:
class de.tutorials.TCPFileExchange$FileProvider Providing file...
overall bytes transfered: 16777216 progress 1%
overall bytes transfered: 33554432 progress 2%
overall bytes transfered: 50331648 progress 2%
overall bytes transfered: 67108864 progress 3%
overall bytes transfered: 83886080 progress 4%
overall bytes transfered: 100663296 progress 5%
overall bytes transfered: 117440512 progress 5%
...
overall bytes transfered: 2097152000 progress 98%
overall bytes transfered: 2113929216 progress 99%
overall bytes transfered: 2130706432 progress 99%
overall bytes transfered: 2143158272 progress 100%
Transfered: 2143158272 bytes in: 189 s -> 11036.612439686767 kbytes/s
Hiermit braucht man für 2gb knapp 3 Minuten (bei 2 verschiedenen Rechnern über 100 MBit Netzwerkkarten verbunden)

Gruß Tom
 
Entschuldigung, dass ich hier ein so altes Thema ausgrabe, aber ich versuche gerade ebenfalls per tcp eine Datei zu übertragen in Java. Die Methode von Thomas gefällt mir ganz gut und ist auch recht schnell. Allerdings werden die Dateien nicht korrekt übertragen, sobald die Dateigröße die Buffergröße überschreitet. Daher würde es mich interessieren, ob es nicht eine Möglichkeit gibt, dafür zu sorgen, die Datenpakete geordnet aufzufangen oder ob vielleicht ein anderer Grund das Problem ist.
 
Der Fehler liegt in Zeile 136, es muss heissen:

Code:
bytesTransfered = fileChannel.transferTo(overallBytesTransferred, Math.min(
                        chunckSizeInBytes, lengthInBytes
                                - overallBytesTransfered), socketChannel);

Sonst beginnt die Datei immer wieder bei 0 zu schreiben.

Gruss david
 
ich hätte nochmal eine frage zu der puffergröße, sollte man die bei übertragungen übers inet verkleinern?
bei direkten übertragungen von pc zu pc, stell ich mir 16mb ein bisschen groß vor, oder wieso diese größe?

Danke im voraus!
 
hi,

wie würde diese variante unter multicast aussehen? ich brauche ungefähr sowas und hab keine ahnung wie das gehen soll^^:
1. habe eine liste von mehreren dateien
2. diese sollen per multicast an verschiedene rechner (clienten) im netzwerk gesendet werden (an definierte ip's)
3. der sender soll eine empfangsnachricht von den clienten bekommen (oder eventuell ne fehlermeldung, wenn das übertragen net geklappt hat)

gruß shinpei
 
hi,

was müsste ich machen, wenn ich das ganze jetzt als multi thread server betreiben will... also dass sich mehrere clienten die datei paralell ziehen können?

gruß planlos

p.s. ich hab schon google usw benutzt... also bitte keine verweise auf documentations... oder so
 
Hallo,

danke für den fix, hab es nun im Beispiel angepasst.

Gruß Tom

Wie sieht nun der korrekte Code aus?

Es wurde geschrieben, dass ab Zeile 136:
Code:
        	bytesTransfered = fileChannel.transferTo(overallBytesTransferred, Math.min(
                    chunckSizeInBytes, lengthInBytes
                            - overallBytesTransfered), socketChannel);

dies so geändert werden sollte.
Da ich Anfänger bin, wäre ich sehr dankbar, wenn mir einer sagen könnte, wie ich overallBytesTransferred integrieren muss, damit der Code richtig gerechnet.
 
Zurück