Dateitransfer über Socket wird nicht korrekt beendet
Hallo, mein erster Post hier Also nicht zu streng mit mir sein! Das richtige Forum sollte ich zumindest schonmal getroffen haben
Also ich bin dabei, einen Chat zu programmieren. Das läuft soweit auch alles ganz fein. Text schicken geht ganz normal, Nachrichten an bestimmte Leute im Chat geht auch.
Jetzt will ich als weiteres Feature die Möglichkeit haben eine Datei an eine bestimmte Person zu schicken.
Das mache ich so, dass ich einen speziellen Befehl ("/transfer NAME") habe. Wenn der Server sieht, dass ein Client einen solchen Befehl geschrieben hat, übermittelt der Server die IP-Adresse des Datei-Verschickenden an den der die Datei erhalten soll.
Vorher hat der Datei-Verschickende nach dem /transfer Befehl einen neuen Thread eröffnet in dem auf eine eingehende Verbindung über ServerSocket gewartet wird.
Der Datei-Erhaltende hat ja die IP des Datei-Verschickenden übermittelt bekommen und macht nun ebenfalls einen neuen Thread auf in dem er sich mittels eines Sockets mit der IP des Datei-Verschickenden verbindet. (das alles auf einem anderen Port als der eigentliche Chat läuft.. eh klar)
Nun besteht also eine extra Verbindung direkt zwischen den beiden Clients.
Jetzt wird die Datei übertragen und die Threads sollten beendet sein.
Nun zu meinem Problem: Die Datei wird zwar übertragen, allerdings wird sie (bei einem kleinen Bild was ich momentan testweise immer verschicke) nicht angezeigt. Versuche ich sie zu löschen bekomm ich eine Meldung, dass die JVM noch darauf zugreifen würde und das deshalb nicht möglich ist...
Erst wenn ich die JVM komplett beende, also den ganzen Chat abschieße ist die Datei anscheinend freigegeben und ich kann sie auch öffnen und sie wird korrekt angezeigt.
Ich teste das ganze hier auf einem Rechner und habe bei meinem /transfer Befehl noch nicht die Möglichkeit eine bestimmte Datei zu verschicken, sondern es wird einfach eine hart reinkodierte Datei verschickt und beim andern Client der auch auf meinem Rechner läuft auf einen anderen Ort an der Festplatte wieder gespeichert.
Ich hoffe ich konnte das einigermaßen gut beschreiben.
Mein Code dazu:
FileSender Klasse:
FileReceiver Klasse:
und hier erfolgt der aufruf in meiner hauptklasse:
das in der run methode, ist der teil wo der client benachrichtigt wird, dass er jetzt ein File bekommt und das in der action-Methode der Teil dass der client jetzt eine nachricht verschickt
Ich hoffe ihr könnt mir weiterhelfen... habe schon einiges probiert. Auf verschiedenste Arten versucht die sockets zu schließen oder die threads zu beenden. mit diesem SO_LINGER attribute rumgespielt. half leider alles nichts...
was auch auffällt, ist dass wenn ich netstat -a eingebe in der windows konsole, die ports immer noch offen sind... was ja eigentlich nicht sein sollte. Also zumindest die für den filetransfer (8766)
Grüße
Simon
Hallo, mein erster Post hier Also nicht zu streng mit mir sein! Das richtige Forum sollte ich zumindest schonmal getroffen haben
Also ich bin dabei, einen Chat zu programmieren. Das läuft soweit auch alles ganz fein. Text schicken geht ganz normal, Nachrichten an bestimmte Leute im Chat geht auch.
Jetzt will ich als weiteres Feature die Möglichkeit haben eine Datei an eine bestimmte Person zu schicken.
Das mache ich so, dass ich einen speziellen Befehl ("/transfer NAME") habe. Wenn der Server sieht, dass ein Client einen solchen Befehl geschrieben hat, übermittelt der Server die IP-Adresse des Datei-Verschickenden an den der die Datei erhalten soll.
Vorher hat der Datei-Verschickende nach dem /transfer Befehl einen neuen Thread eröffnet in dem auf eine eingehende Verbindung über ServerSocket gewartet wird.
Der Datei-Erhaltende hat ja die IP des Datei-Verschickenden übermittelt bekommen und macht nun ebenfalls einen neuen Thread auf in dem er sich mittels eines Sockets mit der IP des Datei-Verschickenden verbindet. (das alles auf einem anderen Port als der eigentliche Chat läuft.. eh klar)
Nun besteht also eine extra Verbindung direkt zwischen den beiden Clients.
Jetzt wird die Datei übertragen und die Threads sollten beendet sein.
Nun zu meinem Problem: Die Datei wird zwar übertragen, allerdings wird sie (bei einem kleinen Bild was ich momentan testweise immer verschicke) nicht angezeigt. Versuche ich sie zu löschen bekomm ich eine Meldung, dass die JVM noch darauf zugreifen würde und das deshalb nicht möglich ist...
Erst wenn ich die JVM komplett beende, also den ganzen Chat abschieße ist die Datei anscheinend freigegeben und ich kann sie auch öffnen und sie wird korrekt angezeigt.
Ich teste das ganze hier auf einem Rechner und habe bei meinem /transfer Befehl noch nicht die Möglichkeit eine bestimmte Datei zu verschicken, sondern es wird einfach eine hart reinkodierte Datei verschickt und beim andern Client der auch auf meinem Rechner läuft auf einen anderen Ort an der Festplatte wieder gespeichert.
Ich hoffe ich konnte das einigermaßen gut beschreiben.
Mein Code dazu:
FileSender Klasse:
Code:
package chat;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class FileSender implements Runnable{
public FileSender() {
}
@Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8766);
Socket socket = serverSocket.accept();
BufferedInputStream fileReader = new BufferedInputStream(new FileInputStream("E:\\Simon\\Desktop\\skigebiete-test4.png"));
BufferedOutputStream fileWriter = new BufferedOutputStream(socket.getOutputStream());
int read = 0;
while ((read = fileReader.read()) != -1) {
fileWriter.write(read);
}
fileReader.close();
fileWriter.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
FileReceiver Klasse:
Code:
package chat;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class FileReceiver implements Runnable {
private String fileHostIP = "";
public FileReceiver(String fileHostIP) {
this.fileHostIP = fileHostIP;
}
@Override
public void run() {
try {
Socket socket = new Socket(fileHostIP, 8766);
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("E:\\Simon\\test.png"));
int read = 0;
while ((read = in.read()) != -1) {
out.write(read);
}
out.close();
in.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
und hier erfolgt der aufruf in meiner hauptklasse:
das in der run methode, ist der teil wo der client benachrichtigt wird, dass er jetzt ein File bekommt und das in der action-Methode der Teil dass der client jetzt eine nachricht verschickt
Code:
public void run()
{
String line;
String command[];
try
{
while(true)
{
line = in.readLine();
command = line.split(" ");
if (line.contains(": /") && command[4].equals("/youGetFile")) {
Thread fileTransfer = new Thread(new FileReceiver(command[5].split(":")[0].substring(1)));
fileTransfer.start();
} else if (line != null)
outputarea.append(line+'\n' );
}
} catch (IOException e) {
e.printStackTrace();
say("Verbindung zum Server abgebrochen");
}
}
public boolean action(Event e, Object what)
{
if (e.target == inputfield)
{
String inp = (String) e.arg;
String[] command = inp.split(" ");
if(command[0].equals("/transfer")) {
out.println(": " + inp);
Thread fileTransfer = new Thread(new FileSender());
fileTransfer.start();
} else {
out.println(": " + inp);
inputfield.setText("");
return true;
}
}
return false;
}
Ich hoffe ihr könnt mir weiterhelfen... habe schon einiges probiert. Auf verschiedenste Arten versucht die sockets zu schließen oder die threads zu beenden. mit diesem SO_LINGER attribute rumgespielt. half leider alles nichts...
was auch auffällt, ist dass wenn ich netstat -a eingebe in der windows konsole, die ports immer noch offen sind... was ja eigentlich nicht sein sollte. Also zumindest die für den filetransfer (8766)
Grüße
Simon
Zuletzt bearbeitet: