Objekte im Netzwerk senden/empfangen

illaX

Erfahrenes Mitglied
Hi,

ich moechte zwischen 2 Rechner Dateien austauschen. Der Sender waehlt die Datei aus und sendet sie.

Dazu der code:
Code:
Socket socket = new Socket(nick.getClientname(), 41001);
                
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                
                if(file.exists())
                    oos.writeObject(file);
                
                oos.flush();
                oos.close();

Der Empfaenger horcht auf dem Socket und wenn er ein Objekt empfaengt soll er auswaehlen wo es gespeichert werden soll.

Ich bekomme es aber nicht hin die Datei zu speichern. Sende ich sie ueberhaupt richtig? Hat jemand Vorschlaege, ideen oder anderes wie ich Daten im Netzwerk austauschen kann?

Danke fuer Hife
 
Hi,

Wer soll diese Datei erhalten? Der Server oder ein Client?

Soweit ich das in Erinnerung habe braucht man dazu einen ServerSocket der über .accept() auf einen Client wartet. Danach hat man einen Socket zu Verfügung auf diesem man dann über einen OutputStream rausschreiben, bzw. über einen InputStream empfangen kann. Auf Client Seite meldet man sich nun bei dem Server an und hat ebenfalls einen Socket mit In- und OutputStream zur Verfügung.

Der InputStream muss auf den "Input" warten, glaube dass das über eine while(true) und read() geht und er dann solange wartet bis sich am "In" was tut. So kann man dann - wie Du es schon hast - Dateien, Objekte,... rausschreiben.

http://www.tutorials.de/forum/search.php?searchid=521432

Gruß

Romsl
 
Hmm, du musst das Objekt erstmal vom Empfänger empfangen, via einer getInputSream Methode und dann kann es der Empfänger auch als Datei abspeichern. also in pseudo Code ungefähr so..
Code:
class Client{
Socket myClient;
public Client(String host, int port){
try {
           myClient = new Socket(host, port);
}
catch (IOException e) {
    System.out.println(e);
}
}
public void saveRecievedObject(){
DataInputStream input = new DataInputStream(myClient.getInputStream());
//und dann kannst du den INputstream weiter verarbeiten z.B. in deine Datei schreiben
}
}
hoffe das wars was du wolltest :)
mfg
elmato
 
OK ich versuche es mal mit einem DataInputStream.

Wie ich die Objekte empfange ist kein Problem. Nur wenn ich die Datei auf der HD speichern moechte, z.B. "D:\Ordner\File.exe" meldet er das es die Datei nicht gibt. Logisch, weil ich sie ja uebers Netzwerk empfangen habe...
 
Damit habe ich das selbe Problem wie sonst auch.

So empfange ich die Daten:

ich lese den InputStream vom Socket.
Er gibt mir dann auch den Pfad + Dateinamen von dem gesendet Objekt aus.

Code:
File file = frame.getFile(); // source file
        
        if(file != null) {
            File newFile = new File(frame.getTfFile().getText());
            
            try {
                FileOutputStream fos = new FileOutputStream(newFile);
                
                DataOutputStream dos = new DataOutputStream(fos);
                
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                
                oos.writeObject(file);
                byte[] array = baos.toByteArray();
                
                dos.write(array);
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }

Das File wird auch erstellt, aber es steht nur schrott drin und der pfad von dem gesendeten File.

Das Problem ist, das ich nicht nur ein Objekt mit Attributen verschicken moechte, sondern Daten die auf meiner Festplatte liegen.
 
Hi,

versteh nicht ganz wozu Du die zwei OutputStream verwendest? Es reicht doch ein OutputStream, auf dem Du die Daten rausschreibst.

Entweder Du schreibst das Object "File" raus, dann musst Du es auf deinem Client auch als File Object behandeln (daher auch der Schrott + Dateiname). Oder Du schreibst die bytes raus und schreibst diese dann auf dem Empfänger in einem FileOutputStream raus ( Encoding achten, bzw. byte[] rausschreiben)

Gruß

Romsl
 
Also ich empfange das File. Da der user es aber in einem anderen Verzeichniss speichern erstelle ich ein neues File.
Die Daten von dem gesendeten File muss ich in das neue File schreiben (1. OutputStream).

Dann muss ich das neue File auf die HD schreiben (2. OutputStream).

Ich glaube ich habe nen ganz falschen Ansatz..
 
Hallo!

Code:
/**
 * 
 */
package de.tutorials;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/**
 * @author daritho
 * 
 */
public class ObjectSerializationExample {
    /**
     * @param args
     */
    public static void main(String[] args) {
        new Thread() {
            public void run() {
                new ObjectSender(4711).start();
            }
        }.start();

        new Thread() {
            public void run() {
                new ObjectReciver("localhost", 4711).start();
            }
        }.start();
    }

    static class ObjectReciver {
        int port;

        String hostname;

        public ObjectReciver(String hostname, int port) {
            this.hostname = hostname;
            this.port = port;
        }

        public void start() {
            ObjectInputStream objectInputStream=null;
            Socket socket=null;
            try {
                socket = new Socket(hostname, port);
                objectInputStream = new ObjectInputStream(socket
                        .getInputStream());
                Object receivedObject = null;
                do {
                    receivedObject = objectInputStream.readObject();
                    System.out.println(this + " received: " + receivedObject);
                } while (receivedObject != null);

            } catch (EOFException e) {
                try {
                    objectInputStream.close();
                    socket.close();
                    System.out.println("Client closed.");
                } catch (IOException e1) {
                    throw new RuntimeException(e1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    static class ObjectSender {

        ServerSocket serverSocket;

        public ObjectSender(int port) {
            try {
                serverSocket = new ServerSocket(port);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void start() {
            try {

                Socket socket = serverSocket.accept();

                ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                        socket.getOutputStream());
                for (int i = 0; i < 10; i++) {
                    Date date = new Date();
                    System.out.println(this + " sending: " + date);
                    objectOutputStream.writeObject(date);
                    objectOutputStream.flush();
                    Thread.sleep(1000L);
                }
                objectOutputStream.close();
                socket.close();
                System.out.println("Server closed.");

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Die Objekt-Serialisierung ist unter Java /SEHR/ langsam... in Zeitkritischen Anwendungen, sollte man die Daten besser ueber einen DataInput/DataOutputStream verschicken, oder eine der Zahlreichen thirdparty Serialisierungs Bibliotheken verwenden.
http://labs.jboss.com/portal/index.html?ctrl:id=page.default.info&project=serialization

Gruss Tom
 
Dank an alle, so wie es aussieht laeuft es jetzt.

Es geht zwar nur sehr sehr langsam (fuer 50MB ca. 5min), aber es geht :D.

Mein Fehler war schon beim senden der Daten...

Hier mal meine Code fuer interessierte:

Klasse TestConnection (Server, empfaengt die Daten);

Code:
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TestConnection extends Thread {

    public TestConnection() {
        super();
        setPriority(Thread.MIN_PRIORITY);
    }

    public void run() {
        super.run();

        try {
            ServerSocket serverSocket = new ServerSocket(41001);

            while (true) {
                Socket socket = serverSocket.accept();

                DataInputStream is = new DataInputStream(socket
                        .getInputStream());

                File tmpFile = new File("d:\\A\\jdk-1_5_0_03-windows-i586-p.exe");

                FileOutputStream fos = new FileOutputStream(tmpFile);

                int i = 0;
                while ((i = is.read()) != -1) {
                    fos.write(i);
                    fos.flush();
                }
                fos.close();
                is.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        TestConnection con = new TestConnection();
        Client client = new Client();

        con.start();
        client.send(null);
    }
}

Klasse Client (connected zum Server und sendet Daten)
Code:
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

    public Client() {
        super();
        
    }

    public void send(Object object) {

        Socket socket = null;
        try {
            socket = new Socket("localhost", 41001);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        File file = new File("D:\\java tools\\jdk-1_5_0_03-windows-i586-p.exe");

        try {

            DataOutputStream dos = new DataOutputStream(socket
                    .getOutputStream());

            FileInputStream fis = new FileInputStream(file);

            int i = 0;
            while ((i = fis.read()) != -1)
                dos.write(i);

            dos.flush();
            dos.close();
            fis.close();
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

    }
}

Ich habe nur das Objekt File verschickt (kann natuerlich nicht funktionieren). Jetzt lese ich die Datei Byte fuer Byte ein und versende sie und der Empfaenger (in dem Fall Server) setzt es wieder zusammen.
 
Hi,

Versuche doch mal nicht nach jedem byte zu flushen, sondern lies eine bestimmte Anzahl von Bytes in ein Array [8 * 1024] - oder evtl. größer - und sende dieses Paket dann. Vielleicht erreichst Du dadurch eine Steigerung der Performance.

Gruß

Romsl
 
Zurück