Datei mittels TCP übertragen

TheNBP

Erfahrenes Mitglied
Hi,
Ich möchte eine Datei die bereits als File Objekt vorliegt mittels TCP (nicht UDP!) auf einen anderen Rechner übertragen.
Ich hab zwar schon ein bischen mit den Sockets herumexperimentiert aber wenn ich mal was verschicken konnte dann kam die Datei unvollständig oder verstümmelt an.

Habe gedacht das Dateiverschicken wäre eine Standardaufgabe und es gäbe vielleicht auch einen Standardcode dazu. In Büchern und im Web hab ich bisher allerdings nur wenig für mich verständliche Hilfe gefunden.

Hat vielleicht jemand ein Codebeispiel für einen DateiServer und einem passenden Client zum empfangen?
 
Hallo!

Datei senden:
Java:
OutputStream out = socket.getOutputStream();
InputStream fileIn = new FileInputStream(file);

byte[] buffer = new byte[1024];
while (fileIn.available() > 0) {
	out.write(buffer, 0, fileIn.read(buffer));
}

fileIn.close();

Datei empfangen:
Java:
InputStream in = socket.getInputStream();
FileOutputStream fileOut = new FileOutputStream("dateiname.ext");
			
byte[] buffer = new byte[1024];
while (socket.isConnected()) {
	int bytesRead = in.read(buffer);
	if (bytesRead == -1) break;
	fileOut.write(buffer, 0, bytesRead);
}

fileOut.close();

Grüße,
Matthias
 

Thomas Darimont

Erfahrenes Mitglied
Hallo!

Also ich wuerde das ganz Straight forward machen:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
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("c:/bigfile-1.0.0.tgz");
        FileProvider fileProvider = new FileProvider(file, 4711);
        FileFetcher fileFetcher = new FileFetcher("localhost", 4711, file
                .getName());
        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...");

                ServerSocket serverSocket = new ServerSocket(this.port);
                Socket socket = serverSocket.accept();

                System.out.println(getClass() + " sending file to: "
                        + socket.getRemoteSocketAddress());

                byte[] buffer = new byte[16384];
                InputStream inputStream = new FileInputStream(this.file);
                OutputStream outputStream = socket.getOutputStream();
                int len = 0;
                while ((len = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, len);
                }

                System.out.println(getClass() + " sending completed");
                inputStream.close();
                outputStream.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    static class FileFetcher implements Runnable {

        String serverName;

        int port;

        String fileName;

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

        public void run() {
            try {
                Socket socket = new Socket(this.serverName, this.port);
                File file = new File(
                        System.getProperty("java.io.tmpdir"),
                        fileName);
                System.out.println(getClass() + " Fetching file... " + file);
                OutputStream outputStream = new FileOutputStream(file);
                InputStream inputStream = socket.getInputStream();

                byte[] buffer = new byte[16384];
                int len = 0;
                while ((len = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, len);
                }
                System.out.println(getClass() + " Fetching complete.");
                outputStream.close();
                inputStream.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Gruss Tom
 

EGJ-Soldier

Mitglied
Hallo zusammen,
Das Programm von Thomas funktioniert bei mir ebenfalls tadellos, jodoch habe ich ein paar fragen, dazu unzwar:

1. Wie kann ich die IP-ändern,
2. Wie kann ich die Portnummer ändern,
3. Wie kann ich eine bestimmte Dateien Laden z.B: D:\Ordner\Ordner\Java.jar und
4. Wie kann ich dem Programm sagen, in welchen Ordner er das Dokument beim anderen Rechner abspeichern soll.

Ich bin mit meinem Latein am Ende :confused:, deswegen bitte ich um Hilfe

Ich danke schonmal im Voraus
EGJ-Soldier
 

takidoso

Erfahrenes Mitglied
Hi,



Frage:
wie kommt man auf die Byte grösse? kann man immer diese im Beispiel verwenden?


Gruss

Nicht das ich das jetzt nachgeprüft hätte,
aber es wird, so vermute ich mal die nächste binäre ermittelte Zahl von der Zielgröße 16000 sein.
also binär 100000000000000 = deimal 16384
und binär 10000000000 = 1024
Warum man sich da solcher Zahlen bedient würde ich so spekulieren, dass vielleicht der verwendete Platz das potential der Codierung möglicherweise besser ausnutzt. aber wie gesagt ist das nu rSpekulation meinerseits.
@ Tom, gibt es da tatsächlichen einen optimierenden Zusammenhang bezüglich JVM, oder ist das nur um sich an binären Zahlengrößen traditionsbewußt zu orientieren?

mit neugierigen Grüßen

Takidoso
 

EGJ-Soldier

Mitglied
Guten Tag ich bin es noch mal,
kann mir echt niemand bei meinen Fragen helfen, es wäre nämlich sehr nett, da ich ein Projekt fertigstellen muss und natürlich die bestmögliche Note ereichen will

ich ware ich für jede Hilfe dankbar:)

gruß EGJ-Soldier
 

takidoso

Erfahrenes Mitglied
Guten Tag ich bin es noch mal,
kann mir echt niemand bei meinen Fragen helfen, es wäre nämlich sehr nett, da ich ein Projekt fertigstellen muss und natürlich die bestmögliche Note ereichen will

ich ware ich für jede Hilfe dankbar:)

gruß EGJ-Soldier

Also ich denke da ist lediglich Phantasie gefragt, oder?
ad 1) & 2) IP und Port kannst Du doch ändern indem Du lediglich einen anderen Port übergibst. Man kann dies zum Beispiel mit einer Properties-Datei bewerkstelligen.
aus 3 und 4 stellt sich bei mir die Frage wie Du das fachlich haben willst. Soll der Client aussuchen können welche Datei er wählt odersoll der Server bestimmten welche Datei er sendet?
Wenn der Client auswhlt und gleichzeitig die "variable" sein soll wäre es vielleicht sinnvoll, wenn er weiß was er beim Server runterladen kann. Man könnte sowas mit einem eigenen Protokoll basteln. Vielleicht hilft Dir das ja weiter:
http://java.seite.net/chat/sockets.html
 
Zuletzt bearbeitet:

EGJ-Soldier

Mitglied
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