# Dateiem senden



## gest01 (21. Jan 2004)

Hallo 

Ich hab mir einen ganz *primitiven*Server und einen Client gebastelt.
Nun möchte ich vom Server eine normale Text-Datei an den Client senden.
Mir ist aber folgendes nicht klar:

-Was für einen Reader muss ich beim Server verwenden,um die Datei einzulesen?
-Was für einen Stream muss vom Server zum Client verwenden???
-Mit welchen Reader muss ich beim Client verwenden um die Bytes zu empfangen?

Wäre toll wenn jemand ein kleines Beispielprogramm hätte.Danke für eure Hilfe.

cu


----------



## nekton (22. Jan 2004)

lohokla hat gesagt.:
			
		

> Hallo
> -Was für einen Reader muss ich beim Server verwenden,um die Datei einzulesen?



fileinput stream und buffered reader wuerde ich mal probieren.



			
				lohokla hat gesagt.:
			
		

> Hallo
> -Was für einen Stream muss vom Server zum Client verwenden???



sockets sind hilfreich . wenn du benutzt kannste sicherlich auch einfach die objekte rueber schmeissen denke ich.



			
				lohokla hat gesagt.:
			
		

> Hallo
> -Mit welchen Reader muss ich beim Client verwenden um die Bytes zu empfangen?



sockets und buffered reader?  alles weitere kommt halt darauf welches modell/protokoll du einsetzt. wenn du einen ftp server schreibst, dann kannst du mit einem ftp client ran gehen. wenn du einen webserver schreibst kannst du halt mit einem browser/httpclient kommunizieren. wenn du dir ein eigenes protokoll ausdenkst musst du einen client programmieren der "die sprache des servers" spricht.


----------



## gest01 (22. Jan 2004)

Hallo

Danke für die Antwort.Ich habe hier mal den Code.

Das ist der Sender:


```
BufferedWriter out = new BufferedWriter(new OutputStreamWriter( client.getOutputStream()) );
BufferedReader in = new BufferedReader(new FileReader("/home/daten/bla.txt"));
while( (line = in.readLine()) != null)
{
        System.out.println(line);
        out.write(line);	
}
in.close();
```

Ich denke das funktiniert ganz gut so-
Hier der Empfänger:

```
BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
String tmp;
while ( (tmp =input.readLine()) != null)
{
       System.out.println(tmp);
}
```


Das Problem ist, Der Empfänger kreist ewig in der while-Schleife.Wie kann kann ich heraus finden,dass der Sender
nichts mehr sendet.So dass die while -Schleife abgebrochen wird?????


----------



## nekton (22. Jan 2004)

eigentlich blockieren die clientsockets selbstaendig solange bis etwas neues reinkommt. ansonsten time das einfach mit threads (quick 'n dirty )

btw. es kann sein dass du etwas anderes brauchst als bufferedreader/bufferedwriter wenn du binaere dateien verschicken willst. ich habe mal eine methode aus meinem altem code kopiert der das http protokoll nutzt um eine datei zu versenden.



```
// this method sends the requested  document to the
// client. when there is any error it calls it 
// self to send an error and an error document.

private void sendFile(String sPath, String sResponse) throws IOExceptiondata back to the 
{										
   String sFileExtension = new String(" ");				
   String sFilePath = this.clearPathString(sPath);
		
   if(sFilePath.lastIndexOf(".") != -1)
   {
      sFileExtension = sFilePath.substring(sFilePath.lastIndexOf(".")+1, sFilePath.length());
   }

   try
   {
      FileInputStream fileStream 	= new FileInputStream(sFilePath);
      PrintStream outStream 		= new PrintStream(this.oClientSocket.getOutputStream());
      int iLen 			= 0;
      byte[] bBuffer 			= new byte[256];

			
      /** send the http protocol response header  **/
      outStream.print("HTTP/1.1 "+ sResponse +"\r\n");
      outStream.print("Server: " + this.sServerName + "\r\n");
      outStream.print("Connection: close\r\n");
      outStream.print("Content-Type: "+ retrMimeType(sFileExtension) +"\r\n\r\n");


      /** send the requested document **/
      try
      {
         outStream = new PrintStream(this.oClientSocket.getOutputStream());
	
         while( (iLen = fileStream.read(bBuffer)) != -1)
   	 {	
            outStream.write(bBuffer, 0, iLen);		// send packages with a maximal size of 
											// 256 Bytes until EOF has been reached
   	 }
      }
      catch(Exception e)
      {
         //eat it!
      }

      fileStream.close();
   }
   catch(FileNotFoundException e)
   {
      sendFile("./errorpages/404.html", "404 Not Found");
   }
	this.oClientSocket.close();					//close the socket and stop the connection
}
```

verlass dich nciht 100% ig auf den code, der mit sicherheit zu verbessern waere (ich war jung und unschuldig )


----------



## gest01 (22. Jan 2004)

Hi 

Danke für den Code.Muss ich mal genauer anschauen.
Mein Problem ist aber vorallem der Empfänger.Ich weiss nicht wie lange ich  "empfangen" soll.
Es werden NUR Textdateien verschickt.

Vielleicht noch ein Tipp  :?:  :?: 

thx&cu


----------



## exorzist (22. Jan 2004)

hallo
ich kenn mich nicht so genau aus, bin noch neuling in der netzwerkprogrammierung, aber vielleicht sollte man solange senden und empfangen bis EOF erreicht ist?!

wenn dieser tipp nicht hilft, einach ignorieren


----------



## nekton (23. Jan 2004)

exorzist hat gesagt.:
			
		

> vielleicht sollte man solange senden und empfangen bis EOF erreicht ist?!



hm, wie gesagt habe ich bisher nur den entsprechenden server zum senden programmiert und den rest uebernahm bei mir der browser, aber das mit eof waere denkbar. einfach mal ausprobieren 

man kann auch einfach die server verbdingun zum client kapseln wenn der server der meinung ist, dass die datei fertig uebrtragen wurde. 

@lohokla: allerdings wuerde ich je nach sinn und zweck des ganzen, an deiner stelle mir ein grundprotokoll ausdenken, das jedesmal klar macht "hallo hier kommt datei XYZ" und "hallo hier ist datei XYZ zu ende". alles eine frage des designs, aber wenn du z.b. mehrere dateien parralel ueber eine socket verbdinung schicken willst, kannst du ja schnell damit durchainander kommen.


----------



## gest01 (29. Jan 2004)

Hi

sorry das ich mich solange nicht gemeldet habe.

Ich habe jetzt einen Sender und Empfänger programmiert.

Hier mal der Server :


```
ServerSocket srvsocket = new ServerSocket(1234);
client = srvsocket.accept();
input = client.getInputStream();
output = client.getOutputStream();
FileInputStream f = new FileInputStream("/home/daten/test.txt");
			byte buffer[] = new byte[4096];
			
			while( f.read(buffer) != -1)
			{
				output.write(buffer);	
				output.flush();
			}
			input.read();
			f.close();
```


Dann noch der Empfänger :


```
Socket client = new Socket("192.168.0.4",1234);
output = client.getOutputStream();
input = client.getInputStream();
String tmp;
byte buffer[] = new byte[4096];
					while( input.read(buffer) != -1)
					{
						tmp = new String(buffer);
						text.append(tmp);
					}
					output.write(1);
```


Der Empfänger schreibt mit text.append(tmp) auf eine JTextArea.Alles funktioniert Wunderbar und schnell!

AUSSER; Beim schreiben des letzten strings (der ja logischerweise nicht mehr 4096 bytes gross ist) fügt er noch mehr Zeichen an.Wisst ihr was ich meine ??? Die befinden sich wohl noch im Array.Wie kann ich das byte-Array löschen?
Die Methode flush() nützt auch nichts :-( 

thx&cu


----------



## nekton (29. Jan 2004)

jaja, das haben wir gerne 

ich denke so oder so aehnlich wuerde ich es machen. angaben allerdings ohne gewaehr 

```
ServerSocket srvsocket = new ServerSocket(1234);
client = srvsocket.accept();
input = client.getInputStream();
output = client.getOutputStream();

String path = "/home/daten/test.txt";
sourceFile = new File(path);
this.fileSizeLeft = sourceFile.length();

if(!sourceFile.isFile())
{
   FileInputStream f = new FileInputStream(this.sourceFile);
   byte buffer[] = this.getBuffer();
			
   while( f.read(buffer) != -1)
  {	
	output.write(buffer);	
	output.flush();

       //gesendete bytes von den bleibenden abziehen
       this.fileSizeLeft -= buffer.length;

        //puffer fuer das naechste paket erzeugen lassen
       byte buffer[] = this.getBuffer();

  }
  input.read();
  f.close();
}



...
File sourceFile;
long fileSizeLeft;
long maxBufferSize = 4096;

//berechnet die benoetigte groeße eines byte-puffers
// anhand der verbleibenden bytes eines datei.
private byte[] getBuffer()
{
   if((this.fileSizeLeft >= this.maxBufferSize) )
   {
      return new byte[(int)this.maxBufferSize];
   }
   else
   {
      return new byte[(int)this.fileSizeLeft]
   }   
}
```

der knackpunkt dabei ist der, das man vorher weiss wie groß die dateigroeße ist, um den puffer dynamisch anpassen zu koennen. das verhindert unnuetzes senden der verbliebenen zeichen.

wenn du das bytearray allerdings wirklich nur leer machen willst, wuerde ich einfach nur ein neues array innerhalb der schleife erzeugen. auch eine nette moeglichkeit waere es natuerlich ein jungfraeuliches array gleicher groeße vorher zu erzeugen und innerhalb der schleife mit  System.arrayCopy(...) drueberzu schreiben.


----------



## gest01 (29. Jan 2004)

Hi 

Danke für die Antwort.

Das Problem ist aber der Empfänger.Wie kann ich dort den Puffer dynamisch anpassen??
Der  Empfänger schreibt ja diese unnützen zeichen von seinem Puffer in das JTextArea??????


----------



## exorzist (29. Jan 2004)

lohokla hat gesagt.:
			
		

> Wie kann ich dort den Puffer dynamisch anpassen??



Kannst du nicht die Dateigrösse ermitteln und diese dann dem Empfänger zwecks Puffer übergeben?
Auch hier gilt, ist der Tipp nutzlos, ignoriere, da ich noch Neuling bin  :###


----------



## nekton (30. Jan 2004)

exorzist hat gesagt.:
			
		

> lohokla hat gesagt.:
> 
> 
> 
> ...



so schlecht ist die idee garnicht und das ist auch der grund warum es sowas wie protokolle gibt. damit derartige probleme vermieden werden. 

wenn lohokla zum beginn des datentransfairs die dateigroeße zum client schicken wuerde, wuesste der wie groß der puffer zum schluss sein muss.

@lohokla: btw. was sind denn das fuer zeichen? die alten aus dem vorhergegangenem durchlauf oder sind es immer die gleichen werte? vieleicht koenntest du ja dein array grundsaetzlich mit dem wert -1 fuer "leer" ueberschrieben. und nach jedem durchlauf das alte array wieder plaetten, wobei ich sagen muss, das der ansatz mit dem protokoll wohl der bessere waere.


----------



## exorzist (30. Jan 2004)

nekton hat gesagt.:
			
		

> so schlecht ist die idee garnicht und das ist auch der grund warum es sowas wie protokolle gibt. damit derartige probleme vermieden werden.


 Ui  :shock: , ich habe hoffnung, dass ich java eines tages sicher kann  :###


----------



## nekton (30. Jan 2004)

das hat nicht viel mit java zu tun als mit allgemeiner logik, was allerdings mindestens genauso wichtig ist wie die programmiersrpache zu kennen.


----------



## exorzist (30. Jan 2004)

nekton hat gesagt.:
			
		

> das hat nicht viel mit java zu tun als mit allgemeiner logik, was allerdings mindestens genauso wichtig ist wie die programmiersrpache zu kennen.


na dann bin ich ja beruhigt [schild=11 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1]habe fertig[/schild]


----------



## gest01 (30. Jan 2004)

Mein Problem ist ,Wenn ich die Dateilänge mit File.length() bestimme,und diese dann mit output.write((int)fileSize) an den client sende,das der client etwas anderes empfängt.??

Hier Sender:


```
File file = new File("/var/log/samba/log.nmbd");
			FileInputStream f = new FileInputStream(file);
			
			fileSize = file.length();
			output.write((int)fileSize);
			System.out.println("LEN :"+(int)fileSize);
```
Empfänger:


```
// Es kommt eine kleinere fileSize an,als abgesendet!!
					fileleSize =input.read()	;	
					byte buffer[] = new byte[fileSize];	
					System.out.println("LEN :"+fileSize);
```

wo liegt denn das Problem?


----------

