# Server Thread beenden



## Guest (7. Jul 2008)

Hallo,

ich möchte einen kleinen messenger erstellen.

ServerStart.java
	
	
	
	





```
import java.awt.event.ActionListener;

/*
 * Server.java
 *
 * Created on 7. Juli 2008, 10:49
 */



/**
 *
 * @author  bmr
 */
public class ServerStart extends javax.swing.JFrame implements ActionListener {
    Server s = new Server();
    
    /** Creates new form Server */
    public ServerStart() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        serverStarten = new javax.swing.JButton();
        serverBeenden = new javax.swing.JButton();
        statusLabel = new javax.swing.JLabel();
        serverStatus = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("Bundle"); // NOI18N
        setTitle(bundle.getString("ServerStart.title")); // NOI18N
        setName("ServerFrame"); // NOI18N
        setResizable(false);

        serverStarten.setText(bundle.getString("ServerStart.serverStarten.text")); // NOI18N
        serverStarten.addActionListener(this);

        serverBeenden.setText(bundle.getString("ServerStart.serverBeenden.text")); // NOI18N
        serverBeenden.addActionListener(this);

        statusLabel.setText(bundle.getString("ServerStart.statusLabel.text")); // NOI18N

        serverStatus.setText(bundle.getString("ServerStart.serverStatus.text")); // NOI18N

        org.jdesktop.layout.GroupLayout mainPanelLayout = new org.jdesktop.layout.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(mainPanelLayout.createSequentialGroup()
                .add(54, 54, 54)
                .add(statusLabel)
                .add(57, 57, 57)
                .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                        .add(serverBeenden, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .add(serverStarten, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .add(serverStatus, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 220, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(18, Short.MAX_VALUE))
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(mainPanelLayout.createSequentialGroup()
                .add(30, 30, 30)
                .add(serverStarten)
                .add(18, 18, 18)
                .add(serverBeenden)
                .add(54, 54, 54)
                .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(statusLabel)
                    .add(serverStatus))
                .addContainerGap(127, Short.MAX_VALUE))
        );

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .add(mainPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(mainPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }

    // Code for dispatching events from components to event handlers.

    public void actionPerformed(java.awt.event.ActionEvent evt) {
        if (evt.getSource() == serverStarten) {
            ServerStart.this.serverStartenActionPerformed(evt);
        }
        else if (evt.getSource() == serverBeenden) {
            ServerStart.this.serverBeendenActionPerformed(evt);
        }
    }// </editor-fold>

private void serverStartenActionPerformed(java.awt.event.ActionEvent evt) {

    if((!s.isStarted)) {
        s.start();
        s.setOnline();
        serverStatus.setText("Server gestartet");
    } else {
        serverStatus.setText("Server ist bereits gestartet");
    }
    mainPanel.validate();
    mainPanel.repaint();
        
}

private void serverBeendenActionPerformed(java.awt.event.ActionEvent evt) {
    s.interrupt();
    serverStatus.setText("Server beendet");
}

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ServerStart().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    private javax.swing.JPanel mainPanel;
    private javax.swing.JButton serverBeenden;
    private javax.swing.JButton serverStarten;
    private javax.swing.JLabel serverStatus;
    private javax.swing.JLabel statusLabel;
    // End of variables declaration

}
```


```
import java.net.*;
import java.io.*;

public class Server extends Thread {

    Boolean isStarted = false;
    

    @Override
    public synchronized void run(){
        while (isStarted) {
            try {
            ServerSocket server = new ServerSocket(4000);
            Socket client = server.accept();
            DataInputStream in = new DataInputStream(client.getInputStream());
            DataOutputStream out = new DataOutputStream(client.getOutputStream());

            String name = in.readUTF();
            String passwort = in.readUTF();
            System.out.println(name + passwort);
            out.writeUTF("ok");
            out.flush();
            in.close();
            out.close();
            } catch (Exception e) {
                System.out.println("Fehler im Server");
            }
        }
    }
    
    public void setOffline() {
        isStarted = false;
    }
    
    public void setOnline() {
        isStarted = true;
    }
}
```

wie kann ich denn einen neu angelgten thread beenden? sollte ich noch mehr ändern? ist mein ansatz  falsch?


----------



## SlaterB (7. Jul 2008)

eine Exception könnte auf ein Ende der Verbindung durch den Client hindeuten,
dass solltest du prüfen und dann die Schleife mit break; verlassen
oder die Schleifenbedingung anpassen

edit: ich habe Server etwas falsch verstanden, der macht ja nochmehr,
wer soll den denn aus welchem Anlass beenden?
du könntest von außen eine boolean-Variable auf true setzen,
die pro Schleifendurchlauf geprüft wird,

solange der Thread aber auf dem Socket hört kann man ihn nicht sauber beenden,
mit einem Timeout dauert das hoffentlich nicht ewig


----------



## Gast (7. Jul 2008)

Naja das ist ja eigentlich auch mein ansatz. Die Methode setOffline bzw Online setzt die boolean variable auf flase bzw true. gut ich hab das hier nicht in der Serverstart Klasse implementiert , hatte das aber zuvor ausprobiert. Damit konnte der Client leider keine Meldung erhalten, dass der Server down ist. Ist mein Ansatz dnen richtig?


----------



## SlaterB (7. Jul 2008)

stand da 
> while (isStarted) 
von Anfang an und nich while (true)?
man oh meter, da habe ich ja wenig genau geschaut

> Ist mein Ansatz dnen richtig?

richtg oder falsch gibts da nicht, das ist eine Möglichkeit, relativ primitiv,
aber je nach Anforderungen völlig ausreichend

> Damit konnte der Client leider keine Meldung erhalten, dass der Server down ist.

was ja auch der Idee, den Server auszuschalten, widerspricht,
wenn der Client noch mit dem Server kommunizieren soll, dann darf er logischerweise nicht ausgeschaltet sein,

stattdessn kannst du eine boolean-Variable baldAusgeschaltet/ nurNochAufAbweiseModus auf true setzen,
einen Timer verwenden, den Client direkt selber ansprechen oder sonst was

du musst schon beschreiben, was genau in allen Situationen passieren soll


----------



## Gast (7. Jul 2008)

wenn der button serverBeenden gedrückt wird sprich seine action perfomed methode aufgerufen wird, so soll der server nicht mehr erreichbar sein. also der client sollte dann dieseselbe fehlermledung erhalten, als wenn der server nie gestartet wurde.

"connection refused"


----------



## SlaterB (7. Jul 2008)

und passiert das nicht beim Ende des Threads durch 
> while (isStarted) { 
?
welches Verhalten beobachtest du denn stattdessen?
was ist die Frage/ das Problem?

(wieso muss ich das nachfragen?  )


----------



## Gast (7. Jul 2008)

also:

ich starte den Server in der Gui.
->Der Client bekommt eine antwort.

ich klicke auf server beenden.
->der client bekommt zunächst noch eine Antowrt
-> ein erneutes ausführen des client codes gibt keine antwort mehr.
-> ich kann eclipse nur noch übe rdie stopteste sagen, dass der client beendet werden soll


----------



## Guest (7. Jul 2008)

```
import java.net.*;
import java.io.*;


public class Client {

	Client() throws IOException {
		Socket server = new Socket("localhost", 4000);
		DataOutputStream out = new DataOutputStream(server.getOutputStream());
		DataInputStream in = new DataInputStream(server.getInputStream());
		out.writeUTF("login1");
		out.writeUTF("passwort");
		out.flush();
		System.out.println(in.readUTF());
		//System.out.println(input.read());
		server.close();
		out.close();
		
		
	}
	
	public static void main(String[] args) {
		try {
			Client client = new Client();
		} catch (IOException e) {
			System.err.println("Fehler: " + e);
		}
	}
}
```


----------



## Gast (7. Jul 2008)

hmm ok ich muss server.close() aufrufen und client.close()

 public synchronized void run(){
...

while(isStarted) {
..
}

   try {
            server.close();
            client.close();
        } catch (IOException ex) {
            System.out.println("put");
        }

allerdings hängt sich meine gui auf, wenn ich nach dem starten auf beende drücke und dann wieder starten will


----------



## SlaterB (7. Jul 2008)

nur noch eine Antwort für den Client ist ja ganz ok, 
die boolean-Variable wirkt sich ja erst auf den nächsten Schleifendurchlauf aus,

vielleicht kannst du direkt nach dem accept auch schon die Variable prüfen und dann irgendwas machen,
der Client hat dann wahrscheinlisch schon erfolgreiche eine Verbindung aufgebaut,
aber in diese wird dann zumindest nicht ok reingeschrieben sondern sofort Ende oder irgendeine 'ach, sollte gar nicht aufgebaut werden'-Nachricht rein

das Socket.accept() kann man wie gesagt nicht beenden, zumindest weiß ich es nicht,
mit TimeOut kann man die vakante Zeit zwischen setOffline() und der nächsten Client-Verbindung minimieren

--------

zur GUI kann man eh noch nichts sagen, falls das eine Frage war,
da braucht man Infos und Code,

falls die oben gepostete Server-GUI gemeint war, kann ich persönlich leider nicht weiterhelfen da ich kein
> org.jdesktop.layout.GroupLayout 
kenne

einen einmal beendeten Thread kann man übrigens nicht wieder starten


----------



## Gast (7. Jul 2008)

org.jdesktop sollte ab jdk 6 dabei sein.
Ich benutze für die gui netbeans.


----------



## FArt (7. Jul 2008)

Nur als Tipp:
deine Streams werden im Fehlerfall nicht geschlossen, isStarted sollte der primitive Datentyp boolean sein, dafür muss aber der Zugriff auf das Flag z.B. über die Deklaration volatile synchronisiert sein.


----------



## Gast (7. Jul 2008)

isStarted ist doch aber boolean ....
was genau ist dieses volatile


----------



## Gast (7. Jul 2008)

Ich bin jetzt einen schritt weiter. Und schon habe ich eine neue Frage:

wie kann ich meinen server anweisen die nachricht eines clients an alle registrierten clients zu schicken. und wie registreire ich diese clients.


----------



## SlaterB (7. Jul 2008)

registrieren: die Objekte, die die einzelnen Verbindungen verwalten, in eine Liste einfügen, irgendwo intelligent zentral gespeichert,
(eine statische Variable ist NICHT schön  )

anweisen:
naja, einfach die Liste durchlaufen und an jeden schicken


----------



## Gast (7. Jul 2008)

welche collection bietet sich denn an?


----------



## SlaterB (7. Jul 2008)

ArrayList


----------

