Dateitransfer in Java (TCP) hin und retour
lima-city → Forum → Programmiersprachen → Java
blockieren
buffer
byte
code
datei
datum
file
http
import
kommunikation
konvertierung
laufen
methode
null
schleife
server
string
url
verbindung
zeile
-
Hallo
Ich will einen ODF-Konvertierungs-Server bauen, welcher mir mit Libreoffice aus Open-Document-Dateien pdfs erstellt. Dieser soll aus Java-Programmen ansprechbar sein.
Das ganze läuft so ab:
Client schickt odf-Datei binär an den Server.
Der Server jagt sie durch die JOD-Bibliothek welche ein horchendes Libreoffice auf dem Server zur Konvertierung verwendet.
Der Server schickt die pdf-Datei binär an den Client zurück.
die Verbindung soll über eine TCP-Verbindung laufen.
Dazu habe ich diesen Server geschrieben, welcher auf Verbindungen wartet und den Transfer sowie die Konvertierung in einem Thread startet:
12345678910111213141516171819202122232425262728293031323334353637383940414243package
cs.exec;
import
java.io.IOException;
import
java.net.ServerSocket;
import
java.net.Socket;
import
threads.TransporterThread;
public
class
ConverterServer {
public
static
void
main(String[] args) {
ServerSocket serverSocket =
null
;
int
i =
0
;
try
{
serverSocket =
new
ServerSocket(
8101
);
}
catch
(IOException e) {
e.printStackTrace();
}
while
(i <
10
){
Socket clientSocket=
null
;
try
{
clientSocket = serverSocket.accept();
TransporterThread ct =
new
TransporterThread(clientSocket);
ct.start();
}
catch
(Exception e) {
e.printStackTrace();
}
i++;
}
try
{
serverSocket.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
Der Thread, welcher die Datei entgegen nimmt, konvertiert und wieder zurück schickt sieht so aus:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677package
threads;
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.Socket;
import
com.artofsolving.jodconverter.DocumentConverter;
import
com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import
com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import
com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
public
class
TransporterThread
extends
Thread {
private
Socket m_client;
private
OutputStream m_outputStream;
private
FileInputStream m_fileInputStream;
private
InputStream m_socketInputStream;
private
FileOutputStream m_fileOutputStream;
private
File m_odt;
private
File m_pdf;
public
TransporterThread(Socket client) {
m_client = client;
}
@Override
public
void
run() {
m_odt =
new
File(
"document.odt"
);
m_pdf =
new
File(
"document.pdf"
);
try
{
m_socketInputStream = m_client.getInputStream();
m_outputStream = m_client.getOutputStream();
m_fileOutputStream =
new
FileOutputStream(m_odt);
byte
[] b1 =
new
byte
[
1024
];
int
bytesRead = m_socketInputStream.read(b1);
while
(bytesRead != -
1
){
m_fileOutputStream.write(b1,
0
,bytesRead);
bytesRead = m_socketInputStream.read(b1);
}
OpenOfficeConnection connection =
new
SocketOpenOfficeConnection(
8100
);
connection.connect();
DocumentConverter converter =
new
OpenOfficeDocumentConverter(connection);
converter.convert(m_odt, m_pdf);
connection.disconnect();
m_fileInputStream =
new
FileInputStream(m_pdf);
byte
[] b2 =
new
byte
[
1024
];
while
(m_fileInputStream.available() >
0
){
m_outputStream.write(b2,
0
, m_fileInputStream.read(b2));
}
m_fileInputStream.close();
m_outputStream.close();
m_fileOutputStream.close();
m_socketInputStream.close();
m_client.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
Der Client ist eine einfache Klasse, welche die Verbindung aufbaut und die odf-Datei schickt.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465package
cc.exec;
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.Socket;
public
class
Client {
public
Client(){
}
public
void
convert(String in, String out){
Socket clientSocket =
null
;
File inFile =
new
File(in);
File outFile =
new
File(out);
try
{
clientSocket =
new
Socket(
"127.0.0.1"
,
13811
);
OutputStream socketOutputStream = clientSocket.getOutputStream();
InputStream socketInputStream = clientSocket.getInputStream();
InputStream fileInputStream =
new
FileInputStream(inFile);
FileOutputStream fileOutputStream =
new
FileOutputStream(outFile);
byte
[] buffer =
new
byte
[
1024
];
while
(fileInputStream.available() >
0
) {
socketOutputStream.write(buffer,
0
, fileInputStream.read(buffer));
}
int
bytesRead = socketInputStream.read(buffer);
while
(bytesRead != -
1
){
fileOutputStream.write(buffer,
0
, bytesRead);
bytesRead = socketInputStream.read(buffer);
}
fileOutputStream.close();
socketInputStream.close();
fileInputStream.close();
socketOutputStream.close();
clientSocket.close();
}
catch
( IOException e) {
e.printStackTrace();
}
try
{
clientSocket.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
Leider blockieren sich die beiden Seiten. Erst wenn ich den Client terminiere beginnt der Server mit der Konvertierung und kann die Datei dann folglich nicht mehr zurück schicken... Hat vieleicht jemand eine Anleitung, wie ich eine Datei von einem Client zu einem horchenden Server und diese anschließend wieder zurück schicken kann?
Nicht über die Ports wundern. Läuft über einen TCP-Tunnel...
Beitrag zuletzt geändert: 6.11.2012 15:20:21 von schrotti12 -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Ich wollte eig. noch folgendes dazu editieren, was das System aber nicht zuließ. Deshalb hier noch eine Erweiterung zum Beitrag:
Wer das Ding in Eclipse nachbauen will findet die Libraries hier: http://www.artofsolving.com/opensource/jodconverter
Bzw. ich hab die beiden Projekte in Eclipse hier als Zip-Dateien verpackt: http://tf.schrotti12.eu
Wie man Libreoffice entsprechend ausführt ist hier nachzulesen: http://www.artofsolving.com/opensource/jodconverter/guide
Beitrag zuletzt geändert: 6.11.2012 15:21:40 von schrotti12 -
Du verwendest nicht zufällig eine Hilfs-Mainclasse zum testen die Client und Server zusammen startet? Ich habe die Erfahrung gemacht, dass das unter Umständen (auch bei entkoppelten Threads) Probleme macht.
Und wo genau bleibt der Server bzw TransporterThread und der Client denn hängen? Die einzigen Methoden die ich im Code sehe die blockieren könnten sind jeweils die .read in Client und TransporterThread bzw die .accept im Server. Alles andere sollte bei einem Fehler eigentlich eine Exception werfen.
mfg -
Der Server erhält die Datei. Das erkenne ich, wenn ich im Dateisystem nachsehe, dass die Document.odf da ist. Aber die Konvertierung startet nicht mehr. Erst wenn ich den Client stoppe (Strg + C) beginnt der Server die Konvertierung.
Server und Client laufen auf unterschiedlichen Maschinen... -
Wie der Server hängen bleibt habe ich soweit schon verstanden, ich hatte eher auf eine Zeilennummer gehofft.
Im TransporterThread nehme ich mal an irgendwo zwischen 53 und 57, der Client steht hochstwahrscheinlich in Zeile 39.
Möglicherweise ist LibreOffice vielleicht doch nicht richtig gestartet und [code=inline]connection.connect();[/code] wartet einfach auf eine Verbindung. Wie genau die Methode funktioniert kann ich dem APIdoc leider nicht entnehmen.
edit: was für ein Blödsinn, sonst würde es ja nachdem der Client gekillt wird auch nicht gehen -.-
edit2: Versuch mal den m_fileOutputStream und/oder m_socketInputStream zu schließen, bevor du die Konvertierung startest.
mfg
Beitrag zuletzt geändert: 6.11.2012 15:42:47 von syberpsace -
Kanns vieleicht sein, dass ich eine neue Socket-Verbindung aufbauen muss? Ich meine dass ich über eine Verbindung nicht Daten hin und her schicken kann? Wäre ja auch blöd...
Ich hab auch schon versucht auf Client- und Server-Seite die nicht mehr benötigten Streams zu schließen, aber irgendwie terminiert er dann auch die Socket-Verbindung... -
Das muss doch blockieren, wenn du das so löst
Überleg dir mal wie sich diese Zeilen verhalten:Die Schleife wird so lange laufen wie kein EOF kommt…1234567byte[] b1 =
new
byte[1024];
int bytesRead = m_socketInputStream.read(b1);
while
(bytesRead != -1){
m_fileOutputStream.write(b1,0,bytesRead);
bytesRead = m_socketInputStream.read(b1);
}
Du hast jetzt 2 Möglichkeiten:
1) du schickst zuerst die Dateigröße an den Server und liest dann genau so viele Bytes, oder
2) du machst das so wie bisher, schließt am Client aber nach der Übertragung der ODT-Datei den OutputStream.
Zu 2)
Das würde ein EOF beim Lesen verursachen und die Schleife würde abbrechen. Daten kannst du dann trotzdem noch vom Server an den Client schicken.
Zu 1)
Bei dieser Methode könnte später noch eine Kommunikation Client → Server stattfinden falls dies benötigt wird, was bei 2) nicht mehr möglich ist. -
Okay, danke! Du hast recht. Er wartet sich wirklch zu Tode. Ich schau mir den Code an und überleg mir, wie ich die Daten übertragen kann. Da komm ich schon noch drauf. Werd das dann nacher veröffentlichen. Ist sicher praktisch, wenn man übers Netzwerk pdfs erstellen kann ohne Libreoffice lokal installieren zu müssen...
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage