Socket Socket is closed

Pommes9485

Bekanntes Mitglied
Hallo,
ich habe das oben genannte Problem. Ich habe einen einfach Lan-Chat programmiert, wobei der server aus einer Klasse und zwei Thread Klassen besteht. Der ie Klasse wartet auf verbindungen und fügt diese gegebenfalls zu einer ArrayList hinzu. Dann wird der erste Thread gestartet, welche immer auf Nachrichten horcht, wenn eine kommt wird diese mit dem dritten Thread an die anderen Clienten geschickt. Ich bin noch am Anfang von Threads und Sockets und mir ist mein Fehler nicht ganz bewusst.
Ich weis zwar, das ich den Socket schließe, aber davor schiebe ich ihn ja noch in eine ArrayList. Hier mein Quellcode, ich denke er sagt mehr als 1000 Sätze. Falls ihr den Stil etwas unschön findet, tut mir das leid, es war auf die schnelle geschrieben.
Java:
import java.util.Scanner; 
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class server
{
ArrayList list = new ArrayList();
public void verbindung() throws IOException
{
ServerSocket server = new ServerSocket(5040);
while(true)
{
Socket client = null;
try
{
client = server.accept();
list.add(client);
hören h1 = new hören(list);
h1.start();
}
catch(IOException e)
{
e.printStackTrace();
System.out.println("Fehler beim Verbinden");
}
finally
{
if (client !=null)
try{client.close();} catch (IOException e){System.out.println(e.getMessage());}
}

}
}
}
Java:
import java.util.Scanner; 
import java.io.*;
import java.net.*;
import java.util.*;
public class hören extends Thread
{
ArrayList list;
Iterator it;
public hören(ArrayList liste){list = liste;it = list.iterator();}
public void run()
{
try{
while(it.hasNext())
{
Socket client = (Socket) it.next();
Scanner in = new Scanner(client.getInputStream());
String nachricht = in.nextLine();
if(!nachricht.equals(null))
{senden send = new senden(list,nachricht);
send.start();
}
}
}
catch(IOException i)
{i.printStackTrace();}

}


}
Java:
import java.util.*; 
import java.io.*;
import java.net.*;
public class senden extends Thread
{
ArrayList list;
Iterator it;
String nachricht;
public senden(ArrayList liste, String nachrichten)
{
list = liste;
it = liste.iterator();
nachricht = nachrichten;
}
public void run()
{
try
{
while(it.hasNext()){
Socket client = (Socket) it.next();
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
out.println(nachricht);

}
}
catch(IOException i)
{
i.printStackTrace();
}
}
}

Danke Für eure Hilfe
 
Zuletzt bearbeitet von einem Moderator:
java-mäßig exakt dasselbe Problem wie hier:
http://www.java-forum.org/netzwerkprogrammierung/119292-serververbindung-sofort-beendet.html
bitte Antwort dort auch lesen 😉

wobei du immerhin auch selber deinen Fehler im Grunde erkennst
> Ich weis zwar, das ich den Socket schließe, aber davor schiebe ich ihn ja noch in eine ArrayList.
schön, dann hast du einen geschlossenen Socket in der Liste?

es hilft nicht, ein Vase bei ebay einzustellen, bevor man sie vom Tisch fallen läßt
 
Ok, aber wenn ich den Socket nicht schließe bringt es auch nichts, dann passiert einfach nichts...
Kann ich denn irgendwie abfragen, ob die verbindung erfolgreich war ?
 
also wenn du schließt bringt das noch weniger hinsichtlich erfolgreich, oder?

ok, du hast jetzt also separat eine andere Frage,
zum Zustand der Verarbeitung an sich kann ich dir System.out.println() empfehlen, Ausgaben wie 'Verbindung hergestellt' usw.

ob etwas über den Socket übertragen wird kann man nur mit deinem bisherigen Code nicht sagen, da gehört auch immer die Client-Gegenseite dazu

doch noch kurz in den Code geschaut:
nachricht.equals(null) ergibt vielleicht eine NullPointerException im equals Code (bei String nicht, in anderen Klassen möglicherweise)
oder direkt eine NullPointerException falls nachricht selber null sein sollte,
auf null vergleicht man mit ==

für jede empfangene Nachricht gleich einen kompletten senden-Thread zu erstellen ist bisschen übertrieben,
zudem ist es zu vermeiden, ständig neue Streams auf die Socket-Streams zu setzen,
erstelle nur einmal Senden, verwende das wieder, setze neue Nachrichten in die Liste von Senden,
verwende Endlos-Schleifen, warte 100 ms und schaue dann wieder ob neue Nachrichten da sind usw.
 
von Natur aus nicht, letztlich mag es so herauskommen, was wiederum aber kein 'aber' wert ist, sondern eben unschön ist,
man stelle sich vor der GarbageCollector würde den nicht mehr benutzten PrintWriter auf den Socket closen(), dann wäre alles aus,

dass man einen PrintWriter ohne close() einfach verschwinden lässt ist als Alternative auch nicht toll, wenn auch vielleicht möglich,
ich will nichts endgültiges vorgeben
 
Danke erstmal, ich bin jetzt auf der Suche nach der Fehlerquelle indem ich an den Try Blöcken die Console etwas ausgeben lasse. Das Problem mit dem Socet Closed habe ich gelöst, indem ich eine Array aus Sockets mache und jeder Socket(leider ob verbindung geschafft oder nicht) wird hinzugefügt. Eine Frage habe ich noch. Wenn ich einen Try Block habe und der oberste Befehl schlägt fehl, lässt er dann alles andere Weg oder probiert er es mit der nächsten zeile ?
 
wenn dir das Konzept der Exceptions und alle bisherigen Begegnungen damit (NulPointerException) nicht die einzig mögliche Antwort geben,
was spricht dann gegen Ausprobieren? mit System.out.println() kann man doch ziemlich genau nachverfolgen, welche Zeile wann dran kommt
 
Ja, das habe ich auch gemacht und dabei werden alle von mir erwünschten Zeilen ausgegeben... Ich werde mir nochmal den Code des Clienten angucken, ob da irgenwo der Fehler ist, denn irgendwo muss er sich ja eingeschlichen haben...

EDIT :
Also, der Fehler liegt vermutlich beim Clienten in der Hören Klasse.
Java:
import java.util.*; 
import java.io.*;
import java.net.*;
public class hören extends Thread
{
Socket server;
public hören(Socket server1){server = server1;}
public void run()
{
System.out.println("Hören run");
while(true)
     {
          try{
              System.out.println("1");
              Scanner in = new Scanner(server.getInputStream());
              System.out.println("2");
              String nachricht = in.nextLine();


              System.out.println("Nachricht empfangen !");
              System.out.println(nachricht);


            }
            catch(IOException i){i.printStackTrace();}
        }
    }
}

Hier wird mir alles ausgegeben, bis auf Nachricht Empfangen und auch die 1 und 2 werden nur einmal ausgegeben. Woran liegt das ?

Mittlerweile habe ich herausgefunden, das es an der while Schleife liegt. Sie wird nur einmal durchlaufen, wenn ich die while Schleife lösche und am Ende von run() "run()" schreibe sehe ich schonmal die Nachricht, aber nur selten und dann wird auch hören als thread nicht mehr ausgeführt.
 
Zuletzt bearbeitet:
in der Schleife jedesmal einen neuen Scanner zu öffnen ist schon wieder dieser Fehler, mehrere Streams auf den Socket-Stream zu legen, es reicht doch einer vor der Schleife?!
bei Input besteht zusätzlich zu den vorherigen Problemen das Problem, dass bei Vorhandensein mehrerer Zeilen ein Scanner alle abgreifen kann (großer Cache), davon nur eine Zeile ausliest und der Rest verloren geht, im nächsten Durchlauf ist für einen neuen Scanner nix mehr da, alle weiteren Zeilen stehen noch im alten Scanner

------

dass überhaupt ganze Zeilen gelesen werden ist oft ein Problem, wenn nämlich die Gegenseite keinen Zeilenumbruch mitschickt,
ich sehe aber nirgendwo Code wo irgendetwas gesendet wird
 
Ich habe jetzt den Scanner noch oben geschrieben und einen Line Separot bei jedem Senden hinzugefügtm ich erhalte die Nachricht auc genau einmal. Aber auch nicht öfter. Der Thread hören Beendet sich dann einfach... Wieso ?
 
wie stellst du das Ende eines Threads fest?
startest du ihn eigentlich mit start() oder mit run()-Aufruf?

wäre schön wenn du gesamtheitlichen Code posten könntest, kompletten Server + Client,
inklusive main-Methoen, Erzeugung der Nachrichten oder Anleitung was man eintippen muss usw.
 
Zuletzt bearbeitet von einem Moderator:
Also, ich mache das momentan noch mit BlueJ, ich hoffe ihr habt das... Daher habe ich auch noch keine Main Methode, wollte es erstmal zum laufen bekommen.
Das der Thread sich beenden merke ich daran, das die Ausgaben, welche aufjeden fall kommen müssten dies nicht tun. Die beiden Ordner sind in einem Zip Verpackt.
Laufen tut es wie folgt :
Server :
server erstellen
--> Methode Verbindung
Client :
main erstellen
--> Verbinden, localhost und port 5040
--> senden(die nachricht)

Das erste mal klappt alles noch einwandfrei, beim zweiten mal nicht mehr. Die Unschönheiten, welche sich auf doppelte Streams und Scanner sowie Printer beziehen, werde ich noch ausmerzen.
 

Anhänge

der Code ist unnötig schlecht geraten, zwar schon vorher sichtbar aber jetzt wo ich damit arbeiten soll muss ich meckern:
niemals eine Klasse mit Umlauten scheiben, kann ich bei mir unter Linux nur schlecht öffnen,
Klassen immer groß schreiben!,
gleiche Klassennamen bei Server und Client ist ziemlich unnötig verwirrend, man weiß nie wo man gerade ist,
keine Klasse main nennen, schon gar nicht kleingeschrieben..

abgesehen davon funktioniert es bei mir anscheinend, mit main-Methoden, bei dir fehlen sie ja, das Senden machst du auch per Klicken?
ok, schreibst du ja auch bereits

mit umbenannter Client-Klasse und main-Methode darin
Java:
	public static void main(String[] args) throws Exception {
		Client c = new Client();
		c.verbinden("localhost", 5040);
		
		Thread.sleep(2000);
		c.senden("test");
	}
erhalte ich als Ausgaben
Code:
Verbindung erfolgreich
Hören run
1
2
Nachricht geschickt!
Nachricht empfangen !
test
1
2
sowie beim Server
Code:
H�ren gestartet [hier den Fehler mit Umlauten noch belassen, schlimm genug]
Nachricht erhalten!
Antwort erhalten !

-------

wie sieht es denn bei dir aus, welche Ausgaben kommen wann, wann nicht, was passiert exakt?

beim Test mit zweiten Client fällt mir aktuell noch auf, dass der Server an seine Hoeren-Klasse die Liste aller Clients übergibt
und Hoeren dann beim ersten Element hört, das ist aber wirklich der erste Client, auf den hören dann zwei, auf den zweiten Client niemand
 
Danke, das du es dir angeguckt hast. Ich werde die Sachen noch entsprechend umschreiben...

Mit zwei Clienten habe ich noch garnicht gearbeitet, aber das Problem tritt schon auf, wenn ich dem selben Clienten eine Nachricht 2 mal schicke, sei es das erste mal "test" und das zweite mal "test2", so kommt nur test an...
 
ok, ich war einerseits auch kurz davor das zu testen, da habe ich gespart,
und auch das ist eigentlich am Code selber zu erkennen, dazu war ich auch zu blind vorher genau hinzuschauen,
aber du selber kannst da auch gar nichts erkennen?

in hoeren im Server ist gar keine richtige Dauerschleife wie im Client (schau dir dort hoeren an!)
sondern es wird nur eine Zeile pro Socket gelesen,
ohne while(true) kann gar nichts dauerhaft funktionieren, das ist doch die Grundfunktion
 
Danke für deine Bemühungen, ich hatte auch wirklich gehofft das es daran liegt, das dies ist nicht der Fall. Es muss beim Clienten irgendwo der Fehler liegen, schließlich müsste der Hören Thread konstanst was ausgeben, tut er aber nicht...
 
ich verstehe nicht ganz was du sagen willst, was umso schwieriger ist, da es Hören ja mehrfach gibt, aber du meinst anscheinend Hören beim Client..

richtig verständlich ist das für mich nicht, du schreibst dass das zweite Senden vom Client an den Server nicht klappt, dies kann ich nachvollziehen und sage dir glasklar, dass das Hören im Server schlecht gebaut ist,
da ist eindeutig ein Fehler zu korrigieren, was willst du erst mal mehr?

mag sein dass es danach immer noch nicht geht, mag sein dass es wie du nun sagst gar an irgendwas im Client liegt,
aber das sind dann nächste Probleme, die muss man eben eins nach dem anderen lösen,
so schlecht wie Hören beim Server bisher war kann man nicht gerade sagen dass man auf der Stelle tritt, sondern es geht aktiv voran

hängt natürlich davon ab wie du das ganze korrigierst, was danach noch Problem ist usw.,
ich kann aus deiner Kurzantwort nicht erkennen ob das noch ein Thema hier ist,
wenn dann mit genauen neuen Code bzw. den geänderten Stellen, genauer Fehlerbeschreibung usw.
 
Java:
import java.util.Scanner; 
import java.io.*;
import java.net.*;
import java.util.*;
public class hören extends Thread
{
ArrayList list;
Iterator it;
public hören(ArrayList liste){list = liste;it = list.iterator();}
public void run()
{
while(true){


while(it.hasNext())
{
Socket client = (Socket) it.next();
try{
Scanner in = new Scanner(client.getInputStream());
String nachricht = in.nextLine();
if(nachricht!=null)
{
System.out.println("Nachricht erhalten!");
senden send = new senden(list,nachricht);
send.start();
}

}
catch(IOException i)
{i.printStackTrace();}

}
}

}
}

So sieht hören jetzt aus, beim Server.

Was ich eben sagen wollt ist, dass es dennoch immernoch nicht funktioniert. Ich vermute es liegt an der hören Klasse vom Client, da diese nur einmal ausgeführt wird, danach geht sie nicht mehr. Wenn ich hingegen einen Zweiten Clienten hinzufüge und damit etwas sende kommt dies auch direkt an. Aber auch nur einmal.
 
deshalb frage ich ja nach dem Code, der ist immer noch 'schlecht', mit den Worten eines alten Kreuzritters ausgedrückt,

der Iterator wird nur einmal durchlaufen, eine while-true-Schleife an sich nützt da nichts,
wenn einmal Iterator durch dann wird es danach zu einer Endlosschleife mit 100% CPU-Belastung,
vom Problem mit mehreren Clients ganz abgesehen

1.
einen Socket bestimmen, die ganze Übergabe der Liste mit Iterator ist störend,
falls du nicht gerade eine Nachricht an viele senden willst, das kann aber später anders geschehen
2.
nur einmal auf dem Socket einen Stream öffen
3.
DANN eine while-true-Schleife,

wie gesagt weitgehend so wie in Hören im Client bereits richtig gemacht..
 
Aber der Server muss ja mehreren zuhören, könnte ich das auch mit einem Thread pro Zuhgehörten Clienten machen ?
Momentan habe ich einfach nur den Socket und den Scanner ganz oben in run() erstellet und erst später, in der While Schleife initsialisert. Aber wie soll ich das ganze ohne den Iterator regeln, wenn nicht mit pro Client einen Thread ...?
 
pro Client ein Thread ist zunächst genau die Lösung, wie überall in Beispielen nachzulesen,
wenn du einen Thread für alle Clients verwenden willst, dann ähnlich deinem bisherigen, aber in jedem while-true-Durchlauf den Iterator neu initialisieren bzw. die Liste auf normalen Wege durchlaufen
(nebenläufiges Einfügen in die Liste durch neuen Client ist in jedem Fall ungünstig)

damit nicht ewig auf einem Client gewartet wird kann ein Timeout helfen, nur 1 sec oder noch weniger bei jedem Client warten,
das kann aber immer noch ewig verzögern, vielleicht doch nicht am falschen Ende sparen und mehr Threads einsetzen..

ich gebe übrigens bewußt keine direkte Code-Hilfe, nachfragen lohnt nicht 😉
nach 'Timeout' etwa suchen falls noch nicht bekannt
 
Zuletzt bearbeitet von einem Moderator:
Ich will auch keine Code Beispiele, dafür bin ich zu Ehrgeizig. Copy und Paste hilft ja nicht beim lernen.
Ich habe es jetzt mit den Threads gemacht und es läuft, sogar mit mehreren Clienten gleichzeitig.
Danke dir !
 

Zurück
Oben