Nach Verbindung gleich ObjectStream empfangen

Bolty

Mitglied
Hallo,

ich habe mich zuletzt recht intensiv mit java.net.* und der Server-Client-Entwicklung beschäftigt.

Als kleinen Test für mich selbst habe ich dann ein Client-Server-basiertes Chatprogramm für mehrere Clients für die Kommandozeile entwickelt, welches auch gut funktioniert hat, aber dennoch sehr simpel war.

Jetzt möchte ich das ganze verbessern, indem ich für den Server und den Client eine graphische Oberfläche entwickle und der User sich zudem mit einem Nickname und weiteren Daten anmelden kann usw.


Zu diesem Zweck möchte ich, dass der Client direkt nach dem verbinden über einen ObjectStream die von mir erstellte Klasse ClientInfo überträgt (werde ich jetzt hier nicht posten, enthält nur ein paar Attribute sowie getter und setter).

Nun bin ich mir nicht sicher, wie ich das realisieren soll; im Grunde wird jeder Client der sich verbindet in einem Thread gehandlet.

Derzeit habe ich folgende Klassen:
serverFrame = grafische Oberfläche, beinhaltet keinen relevanten Code
Server = extends Thread, läuft in Endlosschleife um eingehen Verbindungen anzunehmen.
ClientListener = extends Thread, für jede neue Verbindung (jeden neuen Socket) wird diese Klasse neu instanziert. Hier wird auf das eintreffen des ObjectStreams und dann im Anschluss auf eingehende Nachrichten gewartet.

Mein Problem: Wenn sich ein Client verbindet, aber kein ClientInfo im Anschluss sendet, läuft der Thread ewig weiter und wartet auf einen ObjectStream, ohne eine Möglichkeit diesen beenden zu können. Wie kann ich dieses Problem lösen?

Dieses Problem tritt z.B. auf, wenn ich versuche mit dem alten Kommandozeilenprogramm zu verbinden. Die Verbindung klappt, allerdings erhält der Server dann natürlich kein Object.

Hier der run-Methode der Server-Klasse:
Java:
public synchronized void run()
    {
        try 
        {
            addLogEntry("Starte Server auf Port " + mPort);
            mServerSocket = new ServerSocket(mPort);
            addLogEntry("Server gestartet, Clients können sich verbinden.");
            mServerDispatcher = new ServerDispatcher(mClients);
            /*
             * Endlosschleife um Clientanfragen zu bearbeiten.
             * Wenn ein Client angenommen wurde, wird ein Object (ClientInfo)
             * erwartet. Nach einer gewissen Wartezeit ohne gültiges Objekt
             * soll der Client verworfen werden. Kommt ein gültiges Objekt an, wird
             * dieses in den Clients-Vektor gespeichert.
             * 
             * mClients = Vector, der alle ClientInfos enthält.
             * mMaxUsers = int zum prüfen der maximalen Useranzahl
             */
            while(true)
            {
                try
                {
                    Socket newClient = mServerSocket.accept();
                    if(mClients.size() <= mMaxUsers)
                    {
                        ClientListener newClientInfo = new ClientListener(newClient, mClients);
                        newClientInfo.start();
                        addLogEntry("Neuer User verbunden");
                    }
                }
                catch(Exception e)
                {
                    addLogEntry("User hat versucht sich zu verbinden, ist aber fehlgeschlagen.");
                }
            }
        } 
        catch (IOException ex) 
        {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
   }

Und hier die run-Methode der ClientListener-Klasse:

Java:
public synchronized void run()
    {
        try 
        {
            ObjectInputStream in = new ObjectInputStream(mClient.getInputStream());
            Object o = in.readObject();
            if(o instanceof ClientInfo) 
            {
                mClientInfo = (ClientInfo)o;
                mClientInfo.setConnection(mClient);
                mClients.add((ClientInfo)o);
                in.close();
                
                 try { 
            while (!isInterrupted()) { 
                try { 
                    String message = mSocketReader.readLine(); 
                    if (message == null) 
                        break; 
                    mServerMessageHandler.sendMessage(message); 
                } 
                catch (SocketTimeoutException ste) 
                { 
                    
                } 
            } 
        } catch (IOException ioex) {  
        } 
            }
            else
                mClient.close();
        }
        catch (IOException ex) 
        {
            Logger.getLogger(ClientListener.class.getName()).log(Level.SEVERE, null, ex);
        } 
        catch (ClassNotFoundException ex) 
        {
            Logger.getLogger(ClientListener.class.getName()).log(Level.SEVERE, null, ex);
        }        
    }

Dies wäre eigentlich meine Hauptfrage.

Ansonsten hätte ich noch zwei nebensächliche: Dieses Projekt ist bisher das größte, an dem ich bisher gearbeitet habe, und mir gefällt die Art meiner Programmierung nicht bzw. ich weiß nicht wie ich sie besser machen könnte.

Im Grunde ist ja alles von der serverFrame-Klasse abhängig. Dort werden die Vectoren für die Clients initialisiert und noch einige andere Variablen.
Diese muss ich natürlich weitergeben. Allein die Klasse mClients (ein Vector, der alle ClientInfos hält) wird vom ServerFrame an die Klasse Server weitergegeben, von da an die Klasse ClientListener usw. So kommt es dazu dass ich z.T. sehr lange Konstruktoren für die anderen Klassen habe. Das sieht nicht gut aus und ist auch nicht übersichtlich. Gibt es da bessere Varianten?

Weiterhin würde ich gerne wissen, wie man sicher mit Passwörtern im Sinne dieser Client-Server-Geschichte arbeiten kann.

Ich dachte mir das so: Client schickt password - Server prüft Passwort - Server sendet richtig/falsch.
Ohne dass sowas eventuell mitgesnifft werden kann (quasi Verschlüsselung usw.).

Sorry für die Wall-of-Text und danke für eure Hilfe,

Bolty
 
Zuletzt bearbeitet:

wef34fewrg

Aktives Mitglied
Hey Bolty.

Es gibt eine Methode der Klasse Socket die public void setSoTimeout(int timeout) heisst. Diese wirft eine SocketTimeoutException nachdem die Zeit abgelaufen ist. Du müsstest deinen Code in der ClientListener geringfügig umbauen.

Ansonsten hätte ich noch zwei nebensächliche: Dieses Projekt ist bisher das größte, an dem ich bisher gearbeitet habe, und mir gefällt die Art meiner Programmierung nicht bzw. ich weiß nicht wie ich sie besser machen könnte.

Im Grunde ist ja alles von der serverFrame-Klasse abhängig. Dort werden die Vectoren für die Clients initialisiert und noch einige andere Variablen.
Diese muss ich natürlich weitergeben. Allein die Klasse mClients (ein Vector, der alle ClientInfos hält) wird vom ServerFrame an die Klasse Server weitergegeben, von da an die Klasse ClientListener usw. So kommt es dazu dass ich z.T. sehr lange Konstruktoren für die anderen Klassen habe. Das sieht nicht gut aus und ist auch nicht übersichtlich. Gibt es da bessere Varianten?

Bessere Varianten gibt es immer. ;)

Zur Art. Da hilft üben und vor allem auch das Lesen. Schau dir an wie andere deine Probleme lösen und nimm mit was du gut findest und schmeiss weg, was du nicht brauchst. Oracle, Gurus, Professoren. Alle bringen dir bei wie du programmieren kannst. Entwurfsmuster, strukturiertes Programmieren etc. sind Dinge die man mal googeln kann.
Beispielsweise folgendes.
Du schreibst, deine ServerFrame Klasse ist für die grafische Benutzeroberfläche zuständig. Wieso initialisierst du dann da Clients und andere Variablen? Lass die Klasse ihre Arbeit machen, nämlich Dinge anzeigen lassen. Probier alles in kleine Probleme aufzuteilen und Klassen zu schreiben die ein Teilproblem des großen Problems lösen. Logisch, funktional, ganz egal wie.
Des weiteren solltest du dir einen festen Einrückungsstil zulegen und dich danach halten.
Nicht Java Gurus wie ich haben echt Probleme herauszulesen wo welche Klammer zu welchem Bereich gehört.

Java:
try
        {
            ObjectInputStream in = new ObjectInputStream(mClient.getInputStream());
            Object o = in.readObject();
            if(o instanceof ClientInfo)
            {
                ....               
                 try {
            while (!isInterrupted()) {
                try {
                    String message = mSocketReader.readLine();
                    if (message == null)
                        break;
                    mServerMessageHandler.sendMessage(message);
                }
                catch (SocketTimeoutException ste)
                {
                   
                }
            }
        } catch (IOException ioex) {  
        }
            }
            else
                mClient.close();
        }

Gerade den Abschnitt um die While Schleife finde ich sehr tragisch. :D
Es ist nur eine persönliche Vorliebe, aber ich finde Code, in dem die geöffnete und geschlossene Klammer in einer eigenen Zeile stehen sehr viel besser zu lesen als
Java:
while(---) {
}
sowas. Gerade wenn wild geschachtelt wird bei try -catch, wirds manchmal nicht leicht. Da kann ich das Buch "Auf dem Weg zum Java Profi" von Michael Inden empfehlen, oder falls das Geld nicht da ist mal nach Java Style Guide oder Bad Smells googeln.

Für deine Java Chatanwendung wäre es vielleicht ganz praktisch, wenn du dich mal mit RMI auseinandersetzt. Nutzt auch TCP, aber ermöglicht es dir angemeldete Clients wie Objekte zu behandeln, die auf dem Serverrechner laufen. Gehe davon aus, dass ClientInfo eben genau das tut. Dem Server Infos über sich schicken?! Brauchst du mit RMI alles nicht.

TCP solltest du dir aber vorher weiterhin anschauen. Da kann ich dir Rainer Oechsles Buch "Parallele und verteilte Anwendungen in Java" unglaublich empfehlen. Beim Thema TCP solltest du besonders nicht mit der Zeit geizen, um das Thema öffnen und schließen von Ressourcen zu verstehen, gerade wenn es um das Öffnen und Schließen mehrere Ressourcen geht, was bei dir ja der Fall ist. Die Methode close(); beispielsweise kann eine IOException werfen, was unglaublich viele Programmierer aber nicht beachten.
Auch das kreuz und quere Öffnen und Schließen von Ressourcen kann zu Problemen führen.
In ClientListener öffnest du in Zeile 10 eine TCP Verbindung, aber wenn du da eine IOException geschmissen bekommst, wer schließt dir dann zwei Zeilen darunter den Strom? (Sorry falls ich den Code falsch verstehe bzw. du daran auch gedacht hast. BTW: Falls ich mit der TCP Verbindung richtig liege, wieso baust du die Verbindung in Zeile 12 ab und vor allem wie baust du davor eine Verbindung auf (Portproblem)?)
In dem Bereich solltest du dich mit dem seit Java 7 implementierten Konzept von "try-with-ressources" einlesen. Unglaublich gute Entwicklung, die dir ein paar try-catch Blöcke weg nimmt. Google in dem Zusammenhang Client Server einfach mal nach TCP Seriell/Parallelserver. Da gibts es schon viel.


Zum Rest vielleicht ein ander Mal was, muss jetzt mal schlafen. Freundin meckert :D
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Verbindung nach Serverabsturz wieder aufbauen Netzwerkprogrammierung 9
Dann07 Audio streamen bricht immer ab nach kurzer Zeit Netzwerkprogrammierung 6
G seite nach posten eines html-forms laden Netzwerkprogrammierung 0
N websocket - keine Daten mehr nach ca 80 Sekunden Netzwerkprogrammierung 0
C Gerenderte Website nach der ausführung von JavaScript als HTML Code aus lesen Netzwerkprogrammierung 4
F Wiederverbinden nach socket Abbruch Netzwerkprogrammierung 1
T Socket sendet erst nach socket.close() Netzwerkprogrammierung 2
L Verzeichnisse mit Inhalt nach SMB-Share kopieren Netzwerkprogrammierung 16
N HTTP Apache 4.2.1 HttpClient 302 nach Login und auf den weiteren Seiten. Netzwerkprogrammierung 5
K Socket Chat-GUI eigenes Event nach Empfangen Netzwerkprogrammierung 2
G Cookie Verwaltungs Problem nach Login auf InetSeite (Wo utma-Cookie?) Netzwerkprogrammierung 18
P Datenpakete nach Australien Netzwerkprogrammierung 7
C Socket Identifikation des clients nach der accept() Methode Netzwerkprogrammierung 2
J Nach Dateiversand werden keine Nachrichten mehr übertragen Netzwerkprogrammierung 11
J Nachricht kommt erst nach beendigung der Anwendung an Netzwerkprogrammierung 4
D Socket Automatischer Reconnect nach einem Disconnect. Netzwerkprogrammierung 4
S Socket nach anderen clients im netzwerk suchen Netzwerkprogrammierung 3
B IP nach gewissen Kriterien überprüfen Netzwerkprogrammierung 5
V JNLP startet nicht !!?!! (je nach PC) Netzwerkprogrammierung 1
H Object Cast Problem nach Übertragung mit Log4j Netzwerkprogrammierung 5
DeviAn Über ein Linux Server ein Windows Server nach einer File fragen Netzwerkprogrammierung 6
Q Datein von Windows nach Mac senden Netzwerkprogrammierung 4
L RMI Programm beendet ohne Fehler sofort nach Start (Windows 2000) Netzwerkprogrammierung 7
T Zugriffsverweigerung nach Dateitransfer Netzwerkprogrammierung 7
T Nach Servern suchen Netzwerkprogrammierung 2
K Bad Request nach Form Login in Jakarta HttpClient Netzwerkprogrammierung 4
L nach Servern suchen Netzwerkprogrammierung 2
M ordner nach socket-übertragung defekt Netzwerkprogrammierung 5
B Im eingelesenen Text nach einem Wort suchen Netzwerkprogrammierung 46
M serialisierung funktioniert nur nach neuer instanzierung Netzwerkprogrammierung 3
W fehlerhafte Datei nach Dateitransfer per ServletOutputStream Netzwerkprogrammierung 2
A Client stürzt nach versand ab Netzwerkprogrammierung 13
S Unix Datei vom Server nach Windows übertragen Netzwerkprogrammierung 8
G Port belegt nach Server restart Netzwerkprogrammierung 5
G Socket wird nach Portscann geschlossen Netzwerkprogrammierung 2
N Verarbeitung nach Weiterleitung in Sockets Netzwerkprogrammierung 2
L Frage nach Socket Netzwerkprogrammierung 4
X Kann ich einen Client/Server verbindung hinkriegen die mir alle paar Sekunden die aktuellen Daten per Realtime zuschickt ? Netzwerkprogrammierung 9
F Verbindung zu einem LDAP Server über Java Netzwerkprogrammierung 4
D Verbindung zu Geräten mit gleicher IP aber in unterschiedlichen VLans aufbauen Netzwerkprogrammierung 2
M Socket Socket lehnt Verbindung ab Netzwerkprogrammierung 3
IAmFloppy Socket Nachstellen der Verbindung Netzwerkprogrammierung 6
M Socket Verbindung Matlab(Server) Java(Client) Netzwerkprogrammierung 1
M Socket peer to peer Verbindung zwischen Java und Matlab Netzwerkprogrammierung 0
S Bluetooth Verbindung zwischen Android app und Raspberry Pi 3 Netzwerkprogrammierung 1
S Peer2Peer Verbindung trotz NAT Netzwerkprogrammierung 2
T VPN-Verbindung über Java Netzwerkprogrammierung 4
Aruetiise Socket Verbindung Überprüfen Netzwerkprogrammierung 18
F Socket Verbindung mit Verschlüsselung und Authentifierzung Netzwerkprogrammierung 1
F Probleme mit Connection Reset bei Telnet Verbindung Netzwerkprogrammierung 1
U Client Soap Verbindung wieder schließen Netzwerkprogrammierung 0
M Verbindung zwischen zwei Pc in dem Selben Netzwerk Netzwerkprogrammierung 8
P Socket Socket-Verbindung Input sehr langsam Netzwerkprogrammierung 1
S FTP Verbindung zu einem BS2000 Großrechner mit Commons Net Netzwerkprogrammierung 0
F Einfache Socket Verbindung Netzwerkprogrammierung 2
F Verbindung zwischen Server und handy Netzwerkprogrammierung 1
M TCP Verbindung Byte-weise lesen? Netzwerkprogrammierung 5
Shams Problem mit Eventbus in Verbindung mit Server Netzwerkprogrammierung 0
Z Verbindung zwischen 2 Rechnern über ServerSockets nicht möglich Netzwerkprogrammierung 3
F TCP Client, verbindung aufrecht halten Netzwerkprogrammierung 0
I Swing hängt sich auf bei Verbindung zum Server Netzwerkprogrammierung 3
P RMI Hohe CPU Last RMI Verbindung Netzwerkprogrammierung 4
J Pc - Handy Verbindung? Netzwerkprogrammierung 3
M Socket 2x Proxy multithread-server mit Cross Verbindung Netzwerkprogrammierung 0
T Verbindung zum Server fehlgeschlagen Netzwerkprogrammierung 7
D Einfache Verbindung zu Linux Server und Datei auslesen Netzwerkprogrammierung 13
R Dauerhaft offene Socket-Verbindung? Netzwerkprogrammierung 3
P server - client verbindung (anfänger) Netzwerkprogrammierung 8
G Socket Socket verbindung für Chat System Netzwerkprogrammierung 3
S Socket Socket Verbindung wiederherstellen Netzwerkprogrammierung 16
T Socket Bidirektionale Verbindung mit Sockets Netzwerkprogrammierung 8
N (TCP) Verbindung ohne Portforwarding Netzwerkprogrammierung 12
N Lan-Verbindung erstellen Netzwerkprogrammierung 2
H Socket Java Chat - Verbindung zum Server fehlgeschlagen. Netzwerkprogrammierung 5
A TCP über UDP Verbindung? Netzwerkprogrammierung 10
D TCP Verbindung (Java Client und Visual Basic Server) Netzwerkprogrammierung 12
E Verbindung zu SQL-Datenbank auf einem Server Netzwerkprogrammierung 13
S Socket Applet Client bekommt keine GLOBALE Verbindung zum Server Netzwerkprogrammierung 25
D Server Client Verbindung - Unexpected End of File - Invalid HTTP Response Netzwerkprogrammierung 4
V NullPointerException bei Verbindung zu RabbitMQ-Server Netzwerkprogrammierung 4
B FTP commons net verschlüsselte verbindung Netzwerkprogrammierung 11
C Verbindung zu einem Hostrechner über das Internet herstellen Netzwerkprogrammierung 15
T Socket Client versucht zyklische Verbindung zum Server Netzwerkprogrammierung 4
X Über eine Socket-Verbindung Arrays übergeben Netzwerkprogrammierung 5
P Socket Verbindung über das Internet Netzwerkprogrammierung 2
A Socket Socket Verbindung unterbrochen --> keine Exception Netzwerkprogrammierung 7
S SVNKit - Verbindung zum Repository trennen? Netzwerkprogrammierung 2
P Socket neuer Client - neue(r) Socket/Verbindung geöffnet? Netzwerkprogrammierung 6
M Problem mit Socket-Verbindung Netzwerkprogrammierung 2
X SSH Verbindung zu Remote Datenbank Netzwerkprogrammierung 2
S TCP Verbindung zu Beamer Netzwerkprogrammierung 8
Y server client socket verbindung übers internet aufbauen Netzwerkprogrammierung 8
M ganymed-ssh2.har: ftp-Verbindung über ftp-Proxy Netzwerkprogrammierung 2
D Verbindung zw. zwei Rechnern funzt nicht Netzwerkprogrammierung 5
F Socket Socket Verbindung Netzwerkprogrammierung 10
E Server schließt einfach verbindung? Netzwerkprogrammierung 6
Shoox VPN-Verbindung für Datenbankzugriff Netzwerkprogrammierung 2
X Socket Handy/PC Verbindung unterscheiden Netzwerkprogrammierung 18
O Telnet verbindung Netzwerkprogrammierung 4
Dit_ UDP Verbindung durch Proxy Netzwerkprogrammierung 4

Ähnliche Java Themen

Neue Themen


Oben