# FileSend - Dateien verschicken



## alshir (22. Jun 2004)

Hallo zusammen,

ich habe ein kleines Programm geschrieben, mit dem ich eine Datei versenden kann. Soweit funktioniert das ganze auch ganz gut. Allerdings gibt es einige kleinere Probleme, bei denn ihr mir bestimmt helfen könnt.

1.) Meine Methode getActualIP liefert mir auch schön meine aktuelle IP zurück. Leider die falsche. Denn sie leifert mir meine Netzwerk IP zurück und nicht meine Internet IP. Wie kann ich diese herausbekommen ??? Zur Info: Ich sitze hinter einem Router.

2.) Ich übergebe meinen beiden Methoden sendFile und receiveFile jeweils ein JTextField Objekt aus meiner GUI (wobei GUI für so ein kleiners Progrämmchen ein sehr überladener Begriff ist  ). Diesem gebe ich jeweils einen neuen Inhalt - passend zum Status. Allerdings musste ich feststellen, dass sobald der Socket erzeugt wird keinerlei Veränderungen am Textfeld mehr stattfinden und meine Befehle einfach ignoriert werden. Erst nach dem schliessen des Sockets kann ich wieder den Inhalt ändern. 
Warum ist das so ???

3.) Ich würde gerne den Dateinamen am Anfang des Streams mit übergeben. Wie mache ich das am besten, dass ich erst einen String in den Stream schreibe und danach eine Datei ??? Also dazu ist zu sagen, dass das schreiben ja kein Problem macht. Ich kann ja schliesslich reinschreiben was ich will, aber wie merke ich beim auslesen, dass das String Object zu Ende ist und die Datei anfängt ???


mfg
alshir


P.S.: Anbei mein Code 


```
import java.net.*;
import java.io.*;
import javax.swing.JTextField;


public class FileSend {
    
    public FileSend() {
    }
    
    public static String getActualIP() throws java.net.UnknownHostException
    {
        return InetAddress.getLocalHost().getHostAddress();           
    }
    
    public static void sendFile(JTextField status, File file, InetAddress address, int port) throws IOException
    {
        
        status.setText("Connecting to host: " + " Pillepalle  ");
        Socket server = new Socket(address, port);                    
        status.setText("Transfering");
               
        InetAddress ip = server.getLocalAddress();
                
        try{
            FileInputStream fis = new FileInputStream(file);
            BufferedOutputStream out = new BufferedOutputStream( server.getOutputStream() );
        
            byte[] buffer = new byte[1024];
            byte temp;
        
            try {
                  while( fis.read(buffer) != -1 ){
                  out.write(buffer);
                 }
            }catch (IOException e){
                System.err.println(e);
            }
            out.close();
            fis.close();
            status.setText("Upload complete");
        }catch (FileNotFoundException e){
            System.err.println(e);
        }
        
        server.close();    
    }
    
    public static void receiveFile( JTextField status, String path ) throws IOException
    {
        ServerSocket server = new ServerSocket( 6667 );
        server.setSoTimeout( 60000 );
       
        Socket client = new Socket();
        status.setText("Waiting for client");
        client = server.accept();
        
        status.setText("Transfering");
        InputStream in = client.getInputStream();
        File file = new File("c:/temp.txt");
        FileOutputStream fos = new FileOutputStream(file);
        
        byte buffer[] = new byte[1024];
        
        while( in.read(buffer) != -1 ){
            fos.write(buffer);
        }
        
        fos.close();
        server.close();
        status.setText("Download complete");
    }
    
}
```


----------



## Grizzly (22. Jun 2004)

Hi alshir,



			
				alshir hat gesagt.:
			
		

> [...]1.) Meine Methode getActualIP liefert mir auch schön meine aktuelle IP zurück. Leider die falsche. Denn sie leifert mir meine Netzwerk IP zurück und nicht meine Internet IP. Wie kann ich diese herausbekommen ??? Zur Info: Ich sitze hinter einem Router.[...]



Natürlich liefert Dir der Socket nur die eigene IP-Adresse (und die der Gegenstelle). Welche denn sonst? Das TCP/IP weiss ja nicht, dass Du hinter einem Router sitzt. Du könntest Deinem Router aber per DynDNS o.ä. einen Namen verpassen und dann per InetAddress.getByName(java.lang.String).getHostAddress(); über den Namen die IP-Adresse holen.



			
				alshir hat gesagt.:
			
		

> [...]2.) Ich übergebe meinen beiden Methoden sendFile und receiveFile jeweils ein JTextField Objekt aus meiner GUI (wobei GUI für so ein kleiners Progrämmchen ein sehr überladener Begriff ist  ). Diesem gebe ich jeweils einen neuen Inhalt - passend zum Status. Allerdings musste ich feststellen, dass sobald der Socket erzeugt wird keinerlei Veränderungen am Textfeld mehr stattfinden und meine Befehle einfach ignoriert werden. Erst nach dem schliessen des Sockets kann ich wieder den Inhalt ändern.
> Warum ist das so ???[...]



Ist auch leicht erklärt: Du musst mit Threads arbeiten. Momentan hast Du nur einen Thread. Und der bedient die Oberfläche. Wenn Du denn zum Übertragen der Daten verwendest, kann dieser natürlich nicht mehr die Oberfläche steuern.


----------



## alshir (22. Jun 2004)

Grizzly hat gesagt.:
			
		

> Hi alshir,
> 
> Natürlich liefert Dir der Socket nur die eigene IP-Adresse (und die der Gegenstelle). Welche denn sonst? Das TCP/IP weiss ja nicht, dass Du hinter einem Router sitzt. Du könntest Deinem Router aber per DynDNS o.ä. einen Namen verpassen und dann per InetAddress.getByName(java.lang.String).getHostAddress(); über den Namen die IP-Adresse holen.



Ich hab keine Ahnung von DynDNS, bekomme das aber sicherlich hin  
Ich frage mich dann nur, ober er mir dann nicht die IP des Routers ausgibt. Diese will ich aber nicht wissen, sondern meine IP in die grosse weite Welt hinaus.



			
				Grizzly hat gesagt.:
			
		

> Ist auch leicht erklärt: Du musst mit Threads arbeiten. Momentan hast Du nur einen Thread. Und der bedient die Oberfläche. Wenn Du denn zum Übertragen der Daten verwendest, kann dieser natürlich nicht mehr die Oberfläche steuern.



Das ist mir leicht unklar. Warum ignoriert Java denn meine Befehle zur Veränderung der grafischen Oberfläche,  sobald ich einen Socket geöffnet habe ???? Immerhin sage ich ja deutlichst, dass dies zu tun ist ???

mfg
alshir


----------



## Grizzly (22. Jun 2004)

alshir hat gesagt.:
			
		

> [...]Ich frage mich dann nur, ober er mir dann nicht die IP des Routers ausgibt. Diese will ich aber nicht wissen, sondern meine IP in die grosse weite Welt hinaus.[...]



Mit DynDNS bekommt Dein Router einen Namen im Internet (bspw. router.dyndns.org). Mit diesem Namen ist natürlich die IP Adresse des Router im Internet verknüpft. Würde auch ansonsten nicht viel Sinn machen, da Du ja ansonsten von außen über den Namen gar nicht erreichbar wärst.



			
				alshir hat gesagt.:
			
		

> [...]Das ist mir leicht unklar. Warum ignoriert Java denn meine Befehle zur Veränderung der grafischen Oberfläche,  sobald ich einen Socket geöffnet habe ???? Immerhin sage ich ja deutlichst, dass dies zu tun ist ???



Ich weiss jetzt nicht, welchen Befehl Du benutzt um Java zum Zeichnen aufzufordern. Prinzipiel ist aber die Verwendung von mehreren Thread in dem Fall nicht schlecht, da Du so auch einen "Abbrechen"-Button einbauen kannst.


----------



## Stefan1200 (22. Jun 2004)

alshir hat gesagt.:
			
		

> Ich hab keine Ahnung von DynDNS, bekomme das aber sicherlich hin
> Ich frage mich dann nur, ober er mir dann nicht die IP des Routers ausgibt. Diese will ich aber nicht wissen, sondern meine IP in die grosse weite Welt hinaus.



Grundlagen Netzwerk: Mit dem Internet ist in deinem Netzwerk NUR dein Router verbunden. Dein Rechner ist nur mit dem Router verbunden. Der Router hat nun die Aufgabe, herauszufinden, für welchen Rechner welche Datenpakete sind. Mit anderen Worten, du brauchst die IP von deinem Router im Internet. Dein Rechner HINTERM Router hat keine eigene IP im Internet! Dein Rechner hat nur die IP in deinem Netzwerk, in dem auch dein Router ist.


----------



## alshir (22. Jun 2004)

```
status.setText("Connecting to host: " + " Pillepalle  "); 
Socket server = new Socket(address, port);                    
status.setText("Transfering");
```

Das ist der entscheidene Teil. Java setzt den Textfeldinhalt vor dem Öffnen des Sockets und ignoriert ihn, sobald der Socket geöffnet ist. Das entzieht sich meinem Verständniss.


Zu der IP Geschichte: Es kann doch aber nicht Sinn der Sache sein, dass ich meinem Router eine DynDNS zuweisen muss, nur um die IP herauszubekommen. Immerhin ist er doch mein Gateway in die Aussenwelt. Es muss da doch eine andere Lösung geben, die vor allem ein wenig unabhängiger von der verwendeten Hardware ist. Ich kann doch nicht jedem, der mal eine Datei verschicken will zumuten, so einen Schnickschnack zu machen, nur damit mein Programm auch die korrekte IP wiedergibt.

Hat jemadn eine Idee zu meiner dritten Frage im Anfangspost ???


Schonmal Danke für eure Antworten.

mfg
alshir


----------



## Guest (22. Jun 2004)

Einige Befehle, wie z.B. accept sind blockierend. Das könnte der Grund der Nichtbedienbarkeit der GUI sein. Passende repaints hast du doch eingebaut, oder?


----------



## alshir (22. Jun 2004)

Anonymous hat gesagt.:
			
		

> Einige Befehle, wie z.B. accept sind blockierend. Das könnte der Grund der Nichtbedienbarkeit der GUI sein. Passende repaints hast du doch eingebaut, oder?



Öhem repaints ???

Wasn das ??? Ich habe gedacht sobald ich die Textfeld-Inhalte änder wirds automatisch angezeigt ??? Funktioniert zumindest bei mir so, ausser halt nach einem neuen Socket.


mfg
alshir


----------



## Grizzly (23. Jun 2004)

alshir hat gesagt.:
			
		

> [...]Zu der IP Geschichte: Es kann doch aber nicht Sinn der Sache sein, dass ich meinem Router eine DynDNS zuweisen muss, nur um die IP herauszubekommen. Immerhin ist er doch mein Gateway in die Aussenwelt. Es muss da doch eine andere Lösung geben, die vor allem ein wenig unabhängiger von der verwendeten Hardware ist. Ich kann doch nicht jedem, der mal eine Datei verschicken will zumuten, so einen Schnickschnack zu machen, nur damit mein Programm auch die korrekte IP wiedergibt.[...]



Ich weiss gar nicht, für was Du überhaupt die IP des Routers im Internet brauchst.

Nehmen wir an Du hast die IP 192.168.1.10 in Deinem Netz und der Router die IP 192.168.1.1 im Deinem Netz und die IP 10.69.81.167 im Internet. Dein Gegenüber hat die IP 10.32.182.3 im Internet. In Deinem Programm würdest Du dann als IP für die andere Stelle 10.32.182.3 eingeben und Dein Router würde die Pakete entsprechend routen.

Problematisch wird es nur, wenn die Gegenstelle auch hinter einem Router steckt und auch eine private bzw. nicht-öffentlichen IP besitzt.

Und nur mal als Anmerkung: Bei anderen Programmen, bspw. Spielen, funktioniert das auch nicht anders: Entweder Du gibst die IP des Servers bzw. Mitspielers oder desen DNS Namen an. Oder Du schickst einen Broadcast im entsprechenden Netz (was natürlich im Internet nicht geht - das dürfte Dein Provider sperren). Oder es gibt einen globalen Server, der eine Liste aller Server hält. Jeder Server meldet sich dann beim hoch- unter runterfahren an ihm an oder ab.


----------



## alshir (23. Jun 2004)

Ich brauche die IP, da mein gegenüber per Knopf seine IP herausfinden können soll, um sie mir dann vorläufig per ICQ zukommen zu lassen. Er geht dann in den "Empfangsmodus" und ich schicke an den nun geöffneten Socket die Datei. 

mfg
alshir


----------



## Grizzly (23. Jun 2004)

Dann sollte der Benutzer entweder keinen Router haben, die IP des Routers im Internet wissen oder einen dynamischen DNS Namen haben.

Woher soll das Programm überhaupt wissen bzw. herausbekommen, dass sich im Netz ein Router befindet?

Und wie hast Du das Problem bisher gelöst, wenn Du bspw. über das Internet mit jemand anderen spielen wolltest?


----------



## alshir (23. Jun 2004)

Grizzly hat gesagt.:
			
		

> Und wie hast Du das Problem bisher gelöst, wenn Du bspw. über das Internet mit jemand anderen spielen wolltest?



Das geht normalerweise einfach. Eventuell muss man noch nen Port freigeben.

Ich habe schon überlegt, ob es ein Kommandozeileprogramm gibt, welches mir meine IP anzeigt, dessen Ausgabe ich dann Einlesen und bearbeiten könnte. 
Oder ob ich vielleicht die html Seite von www.whatismyip.com laden und analysieren könnte ???

Das jeder die IP auch so herausfinden kann, ist mir schon klar. Aber ich tue das ja hier zum Spass. Und ich finde das wäre ein angenehmes Gimmick.


mfg
alshir


----------



## Grizzly (23. Jun 2004)

alshir hat gesagt.:
			
		

> Grizzly hat gesagt.:
> 
> 
> 
> ...



Ihr habt Eure IPs dadurch herausgefunden, das Ihr einen Port freigegeben habt??? Wie habt Ihr das denn angestellt? ???:L

Ich weiss ja, dass man den Port bspw. auf einer Firewall auf einen bestimmte IP und einen bestimmten Port hinter der Firewall weiterleiten kann. Aber das man dadurch auch die IP feststellen kann...


----------



## alshir (23. Jun 2004)

Nein das natürlich nicht. Wenn man mal - wie vorsinnflutlich - die IPs für ein Spiel austauschen musste, geht man z.b. auf www.whatismyip.com und liest dort die IP ab.

Aber da die meisten Spiele über einen eigenen Gameserver, der bereitgestellt wird funktionieren, hat man damit heutzutage nichts mehr zutun. 

Aber darum gehts hier nicht  btT

mfg
alshir


----------



## alshir (25. Jun 2004)

So aktueller Zwischenstand: 

Ich parse meine IP von www.whatismyip.com

Dies klappt auch sehr gut mithilfe folgenden Codes:

```
import java.net.*;
import java.io.*;

public class IPbehindaRouter {
    
    /** Creates a new instance of IPTest */
        
    public static String getIP() {
        String line = "";
        BufferedReader in = null;
        int i = 0;
        try{
            URL getyouripurl = new URL( "http://www.whatismyip.com");
            in = new BufferedReader( new InputStreamReader( getyouripurl.openStream() ) );
        } catch (MalformedURLException e) {
            System.err.println(e);
        } catch (IOException e) {
            System.err.println(e);
        }
        try{
            while( (line = in.readLine() ) != null) {
                if( i == 26 ) {
                   return line.substring( 15, (line.length() - 10) );
                }
                i++;
            }
        } catch (IOException e) {
            System.err.println(e);
        }
        return "Fehler";
    }
}
```

Die Übertragung einer Datei innerhalb meines Netzwerks klappt auch wunderbar. Nun will ich eine Verbindung zu jemandem herstellen, der hinter einem Router sitzt. Die IP, unter der der Router im Netz zu erreichen ist, habe ich. Allerdings kommt die Verbindung nicht zustande. Ich vermute, dass es daran liegt, dass ich den Rechner hinter dem Router nicht genau adressieren kann.

Achso die Ports sind natürlich freigegeben.

mfg
alshir


----------



## Grizzly (25. Jun 2004)

alshir hat gesagt.:
			
		

> [...]Die Übertragung einer Datei innerhalb meines Netzwerks klappt auch wunderbar. Nun will ich eine Verbindung zu jemandem herstellen, der hinter einem Router sitzt. Die IP, unter der der Router im Netz zu erreichen ist, habe ich. Allerdings kommt die Verbindung nicht zustande. Ich vermute, dass es daran liegt, dass ich den Rechner hinter dem Router nicht genau adressieren kann.
> 
> Achso die Ports sind natürlich freigegeben.
> 
> ...



Ist ja auch klar: Wenn der Rechner hinter dem Router keine öffentliche routbare Adresse hat (bspw. 192.168.x.x), kannst Du ihn auch nicht erreichen. Wenn die Adresse der Gegenstelle sich nicht in Deinem Netz befindet, muss sie eine öffentliche Adresse sein.


----------



## alshir (25. Jun 2004)

Was bedeutet genau "öffentlich routbare Adresse" ????

Ich meine irgendwie muss es doch möglich sein, dies zu bewerkstelligen ??? Ich meine ich versuche hier ja nicht, die Weltherrschaft an mich zu reißen, sondern nur eine Datei zu versenden.

mfg
alshir


----------



## Grizzly (25. Jun 2004)

Da sich nicht jeder eine eigene Adresse im Internet leisten kann (bspw. ich  ), gibt es Adressen, die nicht in das Internet geroutet werden. Der Router maskiert diese Adressen bei einer Anfrage in das Internet. Die Antwort wird dann vom Router an den Absender durchgestellt.

*Beispiel:*
Ich habe ich eine Router. Lokal hat er die IP-Adresse 192.168.10.1, in das Internet - nehmen wir an - 10.81.19.148. Mein eigener Rechner hat die Adresse 192.168.10.20. Wenn ich nun eine Anfrage in das Internet schicke, geht mein Paket an den Router. Dieser maskiert das Paket und setzt seine eigene Adresse - und zwar die Internet-Adresse 10.81.19.148 - als Absender ein. Wenn nun das Antwort-Paket zurück kommt, demaskiert er das Paket und setzt als Empfänger - wo momentan er mit 10.81.19.148 steht - die Adresse meines Rechners ein.
Die IP-Adresse 192.168.10.20 wird vom Internet aus nicht gesehen. Es sieht von außen so aus, als wäre nur ein Rechner mit der IP 10.81.19.148 unterwegs.

Übrigens sind folgende IP-Bereiche "nicht öffentlich":

Klasse-A-Netzwerk: 10.0.0.0 bis 10.255.255.0
Klasse-B-Netzwerk: 172.16.0.0 bis 172.31.0.0
Klasse-C-Netzwerk: 192.168.0.0 bis 192.168.255.0


----------



## alshir (25. Jun 2004)

So es geht jetzt. Hab beim Empfänger den Port freigeschaltet und lasse das ganze jetzt auf nem Port über 10000 laufen.

Vielen Dank für eure Mühen, ganz besonders dir Grizzly

mfg
alshir


----------



## Grizzly (25. Jun 2004)

Ein Port-Forwarding ist natürlich auch eine Möglichkeit. Die Frage ist bloss, ob das jetzt komformtabler ist. Immerhin muss jetzt einer der beiden immer das Port-Forwarding bei sich einrichten... :wink:


----------

