# ServerSocket sauber beenden



## jonas.to.go (22. Jan 2014)

Hey Leute,
ich hab hier nen winziges Problemchen.
Also wir sollen in der Schule ein Schnick-Schnack-Schnuck-Programm schreiben und zwar auf Basis eines vorgegebenen Chatprogramm.
Leider hat der Programmierer des Chatprogramms (nicht der Lehrer) nicht sehr weit gedacht und keine "Server trennen Funktion" mit eingebaut ebenso wenig wie "Clients vom Server kicken".
Nun musste ich das alles selber machen, was mich durch komplizierte unnötige Programmierung des Vorpragrammierers zu einigen Problemen geführt hat.
Hier erstmal der Programmcode:

GUIClient:

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

/**
 * 
 * @version 1.0 vom 14.01.2014
 * 
 */

public class GUIClient extends JFrame 
{
    private     EchoClient          ec;
    private     Rules               ru;
    private     JButton             bconnect        = new JButton();
    public      JButton             bEchse          = new JButton();
    public      JButton             bPapier         = new JButton();
    public      JButton             bSchere         = new JButton();
    public      JButton             bSpock          = new JButton();
    public      JButton             bStein          = new JButton();
    private     JButton             bRules          = new JButton();
    private     JButton             bExit           = new JButton();
    private     JLabel              jIP             = new JLabel();
    private     JLabel              jNickname       = new JLabel();
    private     JLabel              jPort           = new JLabel();
    private     JTextField          jtIP            = new JTextField();
    private     JTextField          jtPort          = new JTextField();
    private     JTextField          jtNick          = new JTextField();
    private     JScrollPane         jspjtaLog       = new JScrollPane();
    public      JTextArea           jtaLog          = new JTextArea("");
    private boolean b;
    // Ende Attribute

    public GUIClient(String title) 
    { 
          
        // Frame-Initialisierung        
        super(title);
        addWindowListener(new WindowAdapter() 
        {
            public void windowClosing(WindowEvent evt) 
            { 
                dispose(); 
            }
        });
        
            
        int frameWidth = 521; 
        int frameHeight = 345;
        setSize(frameWidth, frameHeight);
        
        
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        
        
        setResizable(false);        
        setVisible(true);
        
        
        // Anfang Komponenten
        Panel cp = new Panel(null);
        add(cp);
        

        bconnect.setBounds(24, 24, 201, 57);
        bconnect.setText("Mit Server verbinden...");
        bconnect.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bconnect);
        bconnect.addActionListener(new ActionListener() 
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bconnect_ActionPerformed(evt);
            }
        });
        
                
        bEchse.setBounds(48, 165, 129, 41);
        bEchse.setText("Echse");
        bEchse.setEnabled(false);
        bEchse.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bEchse);
        bEchse.addActionListener(new ActionListener()
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bEchse_ActionPerformed(evt);
            }
        });
        
        
        bPapier.setBounds(336, 110, 129, 41);
        bPapier.setText("Papier");
        bPapier.setEnabled(false);
        bPapier.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bPapier);
        bPapier.addActionListener(new ActionListener() 
        { 
        public void actionPerformed(ActionEvent evt) 
            { 
                bPapier_ActionPerformed(evt);
            }
        });
        
        
        bSchere.setBounds(48, 110, 129, 41);
        bSchere.setText("Schere");
        bSchere.setEnabled(false);
        bSchere.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bSchere);
        bSchere.addActionListener(new ActionListener()
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bSchere_ActionPerformed(evt);
            }
        });
        
        
        bSpock.setBounds(48, 220, 129, 41);
        bSpock.setText("Spock");
        bSpock.setEnabled(false);
        bSpock.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bSpock);
        bSpock.addActionListener(new ActionListener()
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bSpock_ActionPerformed(evt);
            }
        });
        
        
        bStein.setBounds(192, 110, 129, 41);
        bStein.setText("Stein");
        bStein.setEnabled(false);
        bStein.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bStein);
        bStein.addActionListener(new ActionListener() 
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bStein_ActionPerformed(evt);
            }
        });
        
        
        bRules.setBounds(112, 272, 65, 25);
        bRules.setText("Regeln");
        bRules.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bRules);
        bRules.addActionListener(new ActionListener() 
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bRules_ActionPerformed(evt);
            }
        });
        
        
        bExit.setBounds(24, 272, 65, 25);
        bExit.setText("Exit");
        bExit.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bExit);
        bExit.addActionListener(new ActionListener() 
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bExit_ActionPerformed(evt);
            }
        });
        
        
        jIP.setBounds(360, 24, 59, 25);
        jIP.setText("IP:");
        cp.add(jIP);
        

        jNickname.setBounds(245, 24, 59, 25);
        jNickname.setText("Nickname");
        cp.add(jNickname);
        

        jPort.setBounds(360, 56, 67, 25);
        jPort.setText("Port:");
        cp.add(jPort);
        

        jtIP.setBounds(392, 24, 97, 25);
        jtIP.setText("IP eingeben");
        cp.add(jtIP);
        jtIP.addFocusListener(new java.awt.event.FocusAdapter() 
        {
            public void focusGained(java.awt.event.FocusEvent evt) 
            {
                if(jtIP.getText().equals("IP eingeben"))
                    jtIP.setText("");
            }
        });
        
        
        jtNick.setBounds(245, 56, 97, 25);
        jtNick.setText("Nick eingeben");
        cp.add(jtNick);
        jtNick.addFocusListener(new java.awt.event.FocusAdapter() 
        {
            public void focusGained(java.awt.event.FocusEvent evt) 
            {
                if(jtNick.getText().equals("Nick eingeben"))
                    jtNick.setText("");
            }
        });
        
        
        jtPort.setBounds(392, 56, 97, 25);
        jtPort.setText("Port eingeben");
        cp.add(jtPort);
        jtPort.addFocusListener(new java.awt.event.FocusAdapter() 
        {
            public void focusGained(java.awt.event.FocusEvent evt) 
            {
                if(jtPort.getText().equals("Port eingeben"))
                    jtPort.setText("");
            }
        });

        
        jspjtaLog.setBounds(192, 165, 275, 134);
        jtaLog.setText("\n");
        jspjtaLog.setViewportView(jtaLog);
        jtaLog.setEditable(false);
        cp.add(jspjtaLog);
        
        // Ende Komponenten
        
        b = false;
        
    } // end of public GUIClient
    

    // Anfang Methoden
    public void bconnect_ActionPerformed(ActionEvent evt) 
    {
         if (b == false) 
         {             
            if(jtNick.getText() != "")
            {
                bconnect.setText("Von Server trennen...");
                ec = new EchoClient(jtIP.getText(), Integer.parseInt(jtPort.getText()), jtaLog, this);
                ec.send("ANMELDUNG " + jtNick.getText());
                bPapier.setEnabled(true);
                bSchere.setEnabled(true);
                bStein.setEnabled(true);
                bEchse.setEnabled(true);             
                bSpock.setEnabled(true);
                b = true;
            }
            else
            {
                jtaLog.setText("Bitte gebe einen gültigen Namen ein.");
            }
        } 
        else
        {
            bconnect.setText("Mit Server verbinden...");
            ec.send("ABMELDUNG");
            bPapier.setEnabled(false);
            bSchere.setEnabled(false);
            bStein.setEnabled(false);
            bEchse.setEnabled(false);
            bSpock.setEnabled(false);
            b = false;
        }
    } // end of bconnect_ActionPerformed
    
    
    public void bEchse_ActionPerformed(ActionEvent evt) 
    {
        ec.send("WAHL "+bEchse.getText());
        bPapier.setEnabled(false);
        bStein.setEnabled(false);
        bSchere.setEnabled(false);
        bEchse.setEnabled(false);
        bSpock.setEnabled(false);
    } // end of bSchere_ActionPerformed
    
    
    public void bPapier_ActionPerformed(ActionEvent evt)
    {
        ec.send("WAHL "+bPapier.getText());
        bStein.setEnabled(false);
        bSchere.setEnabled(false);
        bPapier.setEnabled(false);
        bEchse.setEnabled(false);
        bSpock.setEnabled(false);
    } // end of bPapier_ActionPerformed

    
    public void bSchere_ActionPerformed(ActionEvent evt) 
    {
        ec.send("WAHL "+bSchere.getText());
        bPapier.setEnabled(false);
        bStein.setEnabled(false);
        bSchere.setEnabled(false);
        bEchse.setEnabled(false);
        bSpock.setEnabled(false);
    } // end of bSchere_ActionPerformed
    
    
    public void bSpock_ActionPerformed(ActionEvent evt) 
    {
        ec.send("WAHL "+bSpock.getText());
        bPapier.setEnabled(false);
        bStein.setEnabled(false);
        bSchere.setEnabled(false);
        bEchse.setEnabled(false);
        bSpock.setEnabled(false);
    } // end of bSchere_ActionPerformed

    
    public void bStein_ActionPerformed(ActionEvent evt) 
    {
        ec.send("WAHL "+bStein.getText());
        bPapier.setEnabled(false);
        bSchere.setEnabled(false);
        bStein.setEnabled(false);
        bEchse.setEnabled(false);
        bSpock.setEnabled(false);
    } // end of bStein_ActionPerformed

    
    public void bRules_ActionPerformed(ActionEvent evt)
    {
        ru = new Rules("Regeln");
    }
    
    
    public void bExit_ActionPerformed(ActionEvent evt) 
    {
        System.exit(0);
    } // end of bExit_ActionPerformed
       
    
    // Ende Methoden
    public static void main(String[] args) 
    {
        new GUIClient("GUIClient");
    } // end of main

} // end of class GUIClient
```

EchoClient:


```
import javax.swing.*;
/**
 *
 * Beschreibung
 *
 */

public class EchoClient extends Client {

    // Attribute
    GUIClient gc;
    JTextArea ausgabe;

    public EchoClient(String pServerIP, int pServerPort, JTextArea pAusgabe, GUIClient pgc) {
        super(pServerIP, pServerPort);
        this.ausgabe = pAusgabe;
        this.gc = pgc;
    }

    // Anfang Ereignisprozeduren
    public void processMessage(String pMessage) 
    {
        if (pMessage.startsWith("MSG ")) {
            ausgabe.append(pMessage.substring(4)+"\n");
        } else {
            if (pMessage.startsWith("TRUE ")) {
                ausgabe.append("Mit Server verbunden!\n");
            } else {
                if (pMessage.startsWith("FALSE")) {
                    ausgabe.append("Konnte keine Verbindung herstellen!\n");
                } else {
                    if (pMessage.startsWith("WAHL ")) {
                        ausgabe.append("Wahl: "+pMessage.substring(5)+"\n");
                    } else {
                        if (pMessage.startsWith("NAME?")) {
                            ausgabe.append("Du wirst nach deinem Namen gefragt\n");
                        }
                        else {
                            if(pMessage.startsWith("NEU"))
                            {
                                gc.jtaLog.setText("");
                                ausgabe.append("Neues Spiel \n");
                                gc.bSchere.setEnabled(true);
                                gc.bStein.setEnabled(true);
                                gc.bPapier.setEnabled(true);
                            }
                            else {
                                 ausgabe.append(pMessage+"\n");
                        }
                    }
                }
            }
        }
    }
}
}

// Ende Ereignisprozeduren
```

Client


```
public abstract class Client 
{

    //Objektbeziehungen
    private Connection hatVerbindung;
    private Clientempfaenger hatEmpfaenger;
     
    /**
    Hilfsklasse fuer den Client, die in einem eigenen Thread den Empfang einer Nachricht vom Server realisiert.
    @author Horst Hildebrecht
    @version 1.0 vom 15.06.2006
    */
    class Clientempfaenger extends Thread
    {
        // Objekte
        private Client kenntClient;
        private Connection kenntVerbindung;
        
        // Attribute
        private boolean zVerbindungAktiv;
    
        /**
        Der ClientEmpfaenger hat den zugeh&ouml;rigen Client und die zugeh&ouml;rige Connection kennen gelernt.<br>
        @param pClient zugeh&ouml;riger Client, der die einkommenden Nachrichten bearbeitet
        @param pConnection zugeh&ouml;rige Connection, die die einkommenden Nachrichten empfŠngt
        */
        public Clientempfaenger(Client pClient, Connection pConnection)
        {
            kenntClient = pClient;
            kenntVerbindung = pConnection;
            zVerbindungAktiv = true;
        }
        
        /**
        Solange der Server Nachrichten sendete, wurden diese empfangen und an die ClientVerbinedung weitergereicht.
        */
        public void run()
        {
            String lNachricht;
            boolean lNachrichtEmpfangen = true;
            
            do
                if (zVerbindungAktiv)
                {
                    lNachricht = kenntVerbindung.receive();
                    lNachrichtEmpfangen = (lNachricht != null);
                    if (lNachrichtEmpfangen)
                        kenntClient.processMessage(lNachricht); 
                }
            while (zVerbindungAktiv && lNachrichtEmpfangen);
        }
        
        /**
        Der ClientEmpfaenger arbeitet nicht mehr
        */
        public void gibFrei()
        {
            zVerbindungAktiv = false;
        }
        
    }
    
    
    /**
    Der Client ist mit Ein- und Ausgabestreams initialisiert.<br>
    @param pIPAdresse IP-Adresse bzw. Domain des Servers
    @param pPortNr Portnummer des Sockets
    */
    public Client(String pIPAdresse, int pPortNr)
    {
        hatVerbindung = new Connection(pIPAdresse, pPortNr);
        
        try
        {
            hatEmpfaenger = new Clientempfaenger(this, hatVerbindung);
            hatEmpfaenger.start();
        }

        catch (Exception pFehler)
        {
            System.err.println("Fehler beim \u00D6ffnen des Clients: " + pFehler);
        }       
         
    }
    
    public void send(String pMessage)
    {
        hatVerbindung.send(pMessage);
    }

    public String toString()
    {
        return "Verbindung mit Socket: " + hatVerbindung.verbindungsSocket();
    }
    
    /**
     Eine Nachricht vom Server wurde bearbeitet.<br>
     Diese abstrakte Methode muss in Unterklassen &uuml;berschrieben werden.
     @param pNachricht die empfangene Nachricht, die bearbeitet werden soll
    */
    public abstract void processMessage(String pMessage);

    /**
    Die Verbindung wurde mit Ein- und Ausgabestreams geschlossen.
    */
    public void close()
    {
        if (hatEmpfaenger != null)
            hatEmpfaenger.gibFrei();
        hatEmpfaenger = null;
        hatVerbindung.close();
    }

}
```

Connection


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

public class Connection extends Thread
{

    private class PrintlnStream extends PrintStream
    {
        public PrintlnStream(OutputStream out, boolean autoflush)
        {
            super(out, autoflush);
        }
    
        public void println (String s)
        {
            this.print(s + "\r\n");
        }
    
        public void println ()
        {
            this.print("\r\n");
        }
    }

    //Objektbeziehungen
    private Socket hatSocket; // Besser wŠre eine Unterklasse. Wegen des noetigen super-Aufrufs in try nicht moeglich!
    private BufferedReader hatEingabe;
    private PrintlnStream hatAusgabe;
    
    // Attribute
    protected boolean zVerbindungAktiv; // Nur fŸr Unterklassen, die echte Threads sind (ServerVerbindung)
    private String zPartnerAdresse;
    private int zPartnerPort;

    protected Connection(){} // nur aus formalen Gruenden noetig
        
    /**
    Die Verbindung ist mit Ein- und Ausgabestreams initialisiert.
    @param pSocket Socket, der die Verbindung beschreibt
    @param pTestModus Wenn true, werden bei jeder Operation Meldungen auf der Konsole ausgegeben.
    */
    protected Connection(Socket pSocket)
    {
        this.erstelleVerbindung(pSocket);
    }
    
    /**
    Die Verbindung ist mit Ein- und Ausgabestreams initialisiert.
    @param pIPAdresse IP-Adresse bzw. Domain des Partners
    @param pPortNr Portnummer des Sockets
    */
    public Connection(String pIPAdresse, int pPortNr)
    {
        try
        {
            this.erstelleVerbindung(new Socket(pIPAdresse, pPortNr));
        }
        
        catch (Exception pFehler)
        {
            hatSocket = null;
            System.err.println("Fehler beim \u00D6ffnen von Socket: " + pFehler);
        }       

    }
    
    /**
    Die Verbindung ist mit Ein- und Ausgabestreams initialisiert.
    @param pSocket Socket, der die Verbindung beschreibt
    */
    protected void erstelleVerbindung(Socket pSocket)
    {
        hatSocket = pSocket;
        zVerbindungAktiv = true;
        
        try
        {
            // Den Eingabe- und Ausgabestream holen
            hatEingabe = new BufferedReader(new InputStreamReader(hatSocket.getInputStream()));
            hatAusgabe = new PrintlnStream(hatSocket.getOutputStream(), true);
            zPartnerAdresse = this.verbindungsSocket().getInetAddress().toString();
            zPartnerAdresse = zPartnerAdresse.substring(zPartnerAdresse.indexOf('/') + 1);
        zPartnerPort = this.verbindungsSocket().getPort();

        }
  
        catch (Exception pFehler)
        {
            System.err.println("Fehler beim Erzeugen der Streams der Verbindung: " + pFehler);
        }       
     }

    public String toString()
    {
        return "Verbindung mit Socket: " + hatSocket;
    }
    
    /**
    Ein Text wurde in den Ausgabestream geschrieben.
    @param pNachricht Text, der geschrieben werden soll
    */
    public void send(String pMessage)
    {
        try
        {
            hatAusgabe.println(pMessage);
         }

        catch (Exception pFehler)
        {
            System.err.println("Fehler beim Schreiben in der Verbindung: " + pFehler);
        }                        
    }
     
    /**
    Ein Text des Eingabestreams wurde geliefert.
    */
    public String receive()
    {
        String lEingabe = null;

        try
        {
            lEingabe = hatEingabe.readLine();
        }

        catch (Exception pFehler)
        {
            if (zVerbindungAktiv)
                System.err.println("Fehler beim Lesen in der Verbindung: " + pFehler);
        }       
                         
        return lEingabe;
    }
    
  /**
  Die IP-Nummer des Partners wurde geliefert.
  */
  protected String partnerAdresse()
  {
    return zPartnerAdresse;
  }
  
  /**
  Der Port des Partners wurde geliefert.
  */
  protected int partnerPort()
  {
    return zPartnerPort;
  }

  /**
    Der Socket der Verbindung wurde geliefert.
    */
    protected Socket verbindungsSocket()
    {
        return hatSocket;
    }
    
    /**
    Die Verbindung wurde mit Ein- und Ausgabestreams geschlossen.
    */
    public void close()
    {
        zVerbindungAktiv = false;
        
        try
        {
            // Die Streams und den Socket schliessen
            hatEingabe.close(); hatEingabe = null;
            hatAusgabe.close(); hatAusgabe = null;
            hatSocket.close(); hatSocket = null;
         }

        catch (Exception pFehler)
        {
            System.err.println("Fehler beim Schlie\u00DFen der Verbindung: " + pFehler);
        }
    }
        
}
```


----------



## jonas.to.go (22. Jan 2014)

Hier Teil2 des Codes:

Server


```
import java.net.*;
import java.net.Socket;

public abstract class Server extends Connection
{
    // Objekte
    public ServerSocket hatServerSocket;
    private Liste hatVerbindungen;
    private ServerSchleife hatSchleife;
    static int i = 1;

    // Attribute
    private int zPort;

    /**
    Verbindung des Servers mit einem Client.<br>
    Kann nebenl&auml;ufig die empfangenen Nachrichten bearbeiten.
    @author Horst Hildebrecht
    @version 1.0 
     */
    private class ServerConnection extends Connection
    {
        // Objekte
        Server kenntServer;

        /*
        Die ServerVerbindung wurde inialisiert.
        @param pSocket Socket, der die Verbindung beschreibt
        @param pServer Server, den die ServerVerbindung kennen lernt
         */
        protected ServerConnection(Socket pSocket, Server pServer)
        {
            this.erstelleVerbindung(pSocket);
            kenntServer = pServer;
        }

        /**
        Solange der Client Nachrichten sendete, wurden diese empfangen und an die Server weitergereicht.<br>
        Abgebrochene Verbindungen wurden erkannt.
         */
        public void run()
        {
            String lNachricht;

            while (zVerbindungAktiv)
            {
                lNachricht = this.receive();
                if (lNachricht == null)
                {
                    if (zVerbindungAktiv)
                    {
                        kenntServer.closeConnection(this.partnerAdresse(), this.partnerPort());
                    }
                }
                else
                    kenntServer.processMessage(this.partnerAdresse(), this.partnerPort(), lNachricht);
            }
        }

    }   

    public class ServerSchleife extends Thread
    {
        boolean b = true;
        private Server kenntServer;

        public ServerSchleife(Server pServer)
        {
            kenntServer = pServer;
        }

        public void run()
        {
            while (true) // ewige Schleife
            {
                try
                {
                    Socket lClientSocket = kenntServer.hatServerSocket.accept();  //wartet
                    ServerConnection lNeueSerververbindung = new ServerConnection(lClientSocket, kenntServer);
                    // Der Client laeuft in einem eigenen Thread, damit mehrere Clients gleichzeitig
                    // auf den Server zugreifen koennen.
                    kenntServer.ergaenzeVerbindung(lNeueSerververbindung);
                    lNeueSerververbindung.start();
                    if(lClientSocket == null)
                    {
                        i = 0;
                    }
                }
                catch (Exception pFehler)
                {
                    System.out.println("Fehler beim Erwarten einer Verbindung in Server: " + pFehler);
                }    
            }
        }    

        public void kill()
        {
            b = false;
        }
    }

    /**
    @author Hermann Brak, Horst Hildebrecht
    @version 1.0 vom 15.06.2006
     */
    private class Liste
    {
        private Knoten hatBug, kenntAktuelles, hatHeck;

        private int zLaenge;

        private class Knoten
        { 
            private Object kenntInhalt;
            private Knoten kenntVorgaenger, kenntNachfolger;

            public Knoten (Object pInhalt, Knoten pVorgaenger, Knoten pNachfolger)
            {
                kenntInhalt     = pInhalt;
                kenntVorgaenger = pVorgaenger;
                kenntNachfolger = pNachfolger;
            }

            public void setzeInhalt (Object pInhalt)
            {
                kenntInhalt = pInhalt;
            }

            public Object inhalt()
            {
                return kenntInhalt;
            }

            public void setzeNachfolger (Knoten pNachfolger)
            {
                kenntNachfolger = pNachfolger;
            }

            public Knoten nachfolger()
            {
                return kenntNachfolger;
            }

            public void setzeVorgaenger (Knoten pVorgaenger)
            {
                kenntVorgaenger = pVorgaenger;
            }

            public Knoten vorgaenger()
            {
                return kenntVorgaenger;
            }
        }

        public Liste ()
        {
            hatBug         = new Knoten(null,null,null);
            hatHeck        = new Knoten(null,hatBug,null);
            kenntAktuelles = hatBug;
            hatBug.setzeNachfolger(hatHeck);  
            zLaenge        = 0;
        }

        public boolean istLeer()
        { 
            return hatBug.nachfolger() == hatHeck;
        }

        public boolean istDahinter()
        {
            return kenntAktuelles == hatHeck;
        }

        public void vor()
        {
            if (!this.istDahinter())
                kenntAktuelles = kenntAktuelles.nachfolger();
        }

        public void zumAnfang()
        {
            kenntAktuelles = hatBug.nachfolger();
        }

        public Object aktuelles()
        {
            return kenntAktuelles.inhalt();
        }

        public void haengeAn (Object pInhalt)
        {
            Knoten lNeuknoten = new Knoten(pInhalt,hatHeck.vorgaenger(),hatHeck);   
            hatHeck.vorgaenger().setzeNachfolger(lNeuknoten);       
            hatHeck.setzeVorgaenger(lNeuknoten);           
            zLaenge++;
        }

        public void entferneAktuelles()
        {
            if (!(this.istDahinter()))
            {
                this.verketteKnoten(kenntAktuelles.vorgaenger(), kenntAktuelles.nachfolger());
                kenntAktuelles = kenntAktuelles.nachfolger();
                zLaenge--;
            }
        }

        private void verketteKnoten (Knoten pLinksknoten, Knoten pRechtsknoten)
        {
            pLinksknoten.setzeNachfolger(pRechtsknoten);
            pRechtsknoten.setzeVorgaenger(pLinksknoten);
        }

    }

    /**
    Der Server ist initialisiert.
    @param pPortNr Portnummer des Sockets
     */
    public Server(int pPortNr)
    {
        try
        {
            //Socket oeffnen
            hatServerSocket = new ServerSocket(pPortNr);
            zPort = pPortNr;
            hatVerbindungen = new Liste();
            hatSchleife = new ServerSchleife(this);
            System.out.println("Starte die Schleife");
            hatSchleife.start();
        }

        catch (Exception pFehler)
        {
            System.out.println("Fehler beim \u00D6ffnen der Server: " + pFehler);
        }       
    }

    public String toString()
    {
        return "Server von ServerSocket: " + hatServerSocket;
    }

    private void ergaenzeVerbindung(ServerConnection pVerbindung)
    {
        hatVerbindungen.haengeAn(pVerbindung);
        this.processNewConnection(pVerbindung.partnerAdresse(), pVerbindung.partnerPort());
    }

    /**
    Liefert die Serververbindung der angegebenen IP mit dem angegebenen Port, null falls nicht vorhanden.
    @param pClientIP IP-Nummer des Clients der gesuchten Verbindung
    @param pClientPort Port-Nummer des Clients der gesuchten Verbindung
     */  
    private ServerConnection SerververbindungVonIPUndPort(String pClientIP, int pClientPort)
    {
        ServerConnection lSerververbindung;

        hatVerbindungen.zumAnfang();

        while (!hatVerbindungen.istDahinter())
        {
            lSerververbindung = (ServerConnection) hatVerbindungen.aktuelles();
            if (lSerververbindung.partnerAdresse().equals(pClientIP) && lSerververbindung.partnerPort() == pClientPort)
                return lSerververbindung;
            hatVerbindungen.vor();
        }   

        return null; // IP nicht gefunden
    }

    /**
    Eine Nachricht wurde an einen Client geschickt.
    @param pClientIP IP-Nummer des Empf&auml;ngers
    @param pClientPort Port-Nummer des Empf&auml;ngers
    @param pMessage die verschickte Nachricht
     */
    public void send(String pClientIP, int pClientPort, String pMessage)
    {
        ServerConnection lSerververbindung = this.SerververbindungVonIPUndPort(pClientIP, pClientPort);
        if (lSerververbindung != null)
            lSerververbindung.send(pMessage);
        else
            System.err.println("Fehler beim Senden: IP " + pClientIP + " mit Port " + pClientPort + " nicht vorhanden.");
    }

    /**
    Eine Nachricht wurde an alle verbundenen Clients geschickt.
    @param pMessage die verschickte Nachricht
     */
    public void sendToAll(String pMessage)
    {
        ServerConnection lSerververbindung;

        hatVerbindungen.zumAnfang();

        while (!hatVerbindungen.istDahinter())
        {
            lSerververbindung = (ServerConnection) hatVerbindungen.aktuelles();
            lSerververbindung.send(pMessage);
            hatVerbindungen.vor();
        }   
    }

    /**
    Die Verbindung mit der angegebenen IP und dem angegebenen Port wurde geschlossen.<br>
    @param pClientIP IP-Nummer des Clients der zu beendenden Verbindung
    @param pClientPort Port-Nummer des Clients der zu beendenden Verbindung
     */
    public void closeConnection (String pClientIP, int pClientPort)
    {
        ServerConnection lSerververbindung = this.SerververbindungVonIPUndPort(pClientIP, pClientPort);
        if (lSerververbindung != null)
        {
            this.loescheVerbindung(lSerververbindung);
            lSerververbindung.close();
        }
        else
            System.err.println("Fehler beim Schlie\u00DFen der Verbindung: IP " + pClientIP + " mit Port " + pClientPort + " nicht vorhanden.");
        this.processClosedConnection(pClientIP, pClientPort);
    }

    /**
    Eine Verbindung wurde aus der Empf&auml;ngerliste gel&ouml;scht.
    @param pVerbindung die zu l&ouml;schende Verbindung
     */
    private void loescheVerbindung(ServerConnection pVerbindung)
    {
        hatVerbindungen.zumAnfang();

        while (!hatVerbindungen.istDahinter())
        {
            ServerConnection lClient = (ServerConnection) hatVerbindungen.aktuelles();
            if (lClient == pVerbindung)
                hatVerbindungen.entferneAktuelles();
            hatVerbindungen.vor();
        }   
    }

    /**
    Ein neuer Client hat sich angemeldet.<br>
    Diese leere Methode kann in einer Unterklasse realisiert werden (Begr&uuml;&szlig;ung).
    @param pClientIP IP-Nummer des Clients, der neu angemeldet ist
    @param pClientPort Port-Nummer des Clients, der neu angemeldet ist
     */
    public void processNewConnection(String pClientIP, int pClientPort)
    {}

    /**
    Eine Nachricht von einem Client wurde bearbeitet.<br>
    Diese leere Methode sollte in Unterklassen &uuml;berschrieben werden.
    @param pClientIP IP-Nummer des Clients, der die Nachricht geschickt hat
    @param pClientPort Port-Nummer des Clients, der die Nachricht geschickt hat
    @param pMessage Die empfangene Nachricht, die bearbeitet werden soll
     */
    public void processMessage(String pClientIP, int pClientPort, String pMessage)
    {}

    /**
    Die Verbindung mit einem Client wurde beendet oder verloren.<br>
    Diese leere Methode kann in einer Unterklasse realisiert werden.
    @param pClientIP IP-Nummer des Clients, mit dem die Verbindung beendet wurde
    @param pClientPort Port-Nummer des Clients, mit dem die Verbindung beendet wurde
     */
    public void processClosedConnection(String pClientIP, int pClientPort)
    {}

    /**
    Der Server wurde geschlossen.
     */
    public void close()
    {
        try
        {
            hatServerSocket.close(); 
            hatServerSocket = null;            
        }
        catch (Exception pFehler)
        { 
             System.err.println("");
        }     
    }

   
}
```


----------



## jonas.to.go (22. Jan 2014)

Hier Teil3 des Codes:

EchoServer


```
import java.net.*;
import java.io.IOException;
import javax.swing.*;
/**
 *
 * Beschreibung
 *
 * @version 1.0 vom 23.03.2009
 * @author
 */

public class EchoServer extends Server {

    // Anfang Variablen
    JTextArea protokoll;
    TeilnehmerListe teilnehmerliste;
    GUIServer gs;
    int teilnehmerzahl;
    int eingang;
    String wahlSpieler1;
    String nick1;
    String wahlSpieler2;
    String nick2;
    String s1, s2;
    String ip1, ip2;
    int p1, p2;
    

    public EchoServer(int pPortNr, JTextArea protokoll, GUIServer pgs) {
        super(pPortNr);
        this.protokoll = protokoll;
        this.gs = pgs;
        teilnehmerliste = new TeilnehmerListe();
        teilnehmerzahl = 0;
        eingang = 0;
    }

    // Anfang Ereignisprozeduren
    public void processMessage(String pClientIP, int pClientPort, String pMessage) 
    {
        s1 = "";
        s2 = "";       
        String name = teilnehmerliste.gibName(pClientIP, pClientPort);
        this.protokoll.append(name+": "+pMessage+"\n");
        this.protokoll.select(protokoll.getText().length(),protokoll.getText().length());
        if (pMessage.startsWith("ANMELDUNG ")) 
        {
            if (teilnehmerzahl < 2)
            {
                String nick = pMessage.substring(10);
                if (teilnehmerliste.hinzufuegen(pClientIP, pClientPort, nick) == true) 
                {
                    this.sendToAll("MSG '"+nick+"' hat sich angemeldet.");
                    teilnehmerzahl++;
                } 
                else 
                {
                    send(pClientIP, pClientPort, "FALSE 02");
                }
            }
            else
            {
                send(pClientIP, pClientPort, "FALSE");
            }
        }
        else 
        {
            if (pMessage.startsWith("WAHL ")) 
            {
                if (eingang == 0)
                {
                    wahlSpieler1 = pMessage.substring(5);
                    nick1 = teilnehmerliste.gibName(pClientIP, pClientPort);
                    eingang++;
                }

                else
                {
                    wahlSpieler2 = pMessage.substring(5);
                    s1 = wahlSpieler1;
                    s2 = wahlSpieler2;  
                    nick2 = teilnehmerliste.gibName(pClientIP, pClientPort);
                    this.sendToAll("MSG '"+nick1+"' wählt: "+wahlSpieler1);
                    this.sendToAll("MSG '"+nick2+"' wählt: "+wahlSpieler2);
                    switch (s1)
                    {
                        case "Schere":
                            switch (s2)
                            {
                                case "Schere":
                                    this.sendToAll("MSG Untschieden!");
                                    gs.jtaLog.append("Unentschieden!");
                                    break;
                                case "Stein":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);      
                                    break;
                                case "Papier":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                case "Spock":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                case "Echse":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                default:
                                    this.sendToAll("MSG Warum geht das nicht?Schere");
                            }
                            break;
                        case "Stein":
                            switch (s2)
                            {
                                case "Schere":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                case "Stein":
                                    this.sendToAll("MSG Untschieden!");
                                    gs.jtaLog.append("Unentschieden!");      
                                    break;
                                case "Papier":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                case "Spock":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                case "Echse":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                default:
                                    this.sendToAll("MSG Warum geht das nicht?Schere");
                            }
                            break;
                        case "Papier":
                            switch (s2)
                            {
                                case "Schere":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                case "Stein":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);      
                                    break;
                                case "Papier":
                                    this.sendToAll("MSG Untschieden!");
                                    gs.jtaLog.append("Unentschieden!");
                                    break;
                                case "Spock":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                case "Echse":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                default:
                                    this.sendToAll("MSG Warum geht das nicht?Schere");
                            }
                            break;
                        case "Spock":
                            switch (s2)
                            {
                                case "Schere":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                case "Stein":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);      
                                    break;
                                case "Papier":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                case "Spock":
                                    this.sendToAll("MSG Untschieden!");
                                    gs.jtaLog.append("Unentschieden!");
                                    break;
                                case "Echse":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                default:
                                    this.sendToAll("MSG Warum geht das nicht?Schere");
                            }
                            break;
                        case "Echse":
                            switch (s2)
                            {
                                case "Schere":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);
                                    break;
                                case "Stein":
                                    this.sendToAll("MSG '"+nick2+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick2);      
                                    break;
                                case "Papier":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                case "Spock":
                                    this.sendToAll("MSG '"+nick1+"' hat gewonnen! Gut gemacht! :)");
                                    gs.jtaLog.append("GEWONNEN: "+nick1);
                                    break;
                                case "Echse":
                                    this.sendToAll("MSG Untschieden!");
                                    gs.jtaLog.append("Unentschieden!");
                                    break;
                                default:
                                    this.sendToAll("MSG Warum geht das nicht?Schere");
                            }
                            break;
                        default:                      
                            this.sendToAll("MSG Warum geht das nicht?s1");
                    } 
                    eingang = 0;
                }
            }
            else 
            {
                if(pMessage.startsWith("NEU"))
                {
                    this.sendToAll("NEU");
                }
                if (pMessage.startsWith("ABMELDUNG"))
                {
                    processClosedConnection(pClientIP, pClientPort);
                }
            }
        }
    }
    
    public void processNewConnection(String pClientIP, int pClientPort) 
    {
        this.send(pClientIP,pClientPort,"NAME?");
    }
    
    public void processClosedConnection(String pClientIP, int pClientPort) 
    {
        String nick = teilnehmerliste.gibName(pClientIP, pClientPort);
        //this.closeConnection(pClientIP,pClientPort);
        teilnehmerliste.entfernen(nick);
    }
    public void closeSocket(ServerSocket s)
    {
        ip1 = "";
        ip2 = "";
        p1 = 0;
        p2 = 0;
        try
        {
            switch(teilnehmerzahl)
            {
                case(1):
                    ip1 = teilnehmerliste.gibIP(nick1);
                    p1 = teilnehmerliste.gibPort(nick1);
                    s.close();
                    break;
                case(2):
                    ip1 = teilnehmerliste.gibIP(nick1);
                    p1 = teilnehmerliste.gibPort(nick1);
                    ip2 = teilnehmerliste.gibIP(nick2);
                    p2 = teilnehmerliste.gibPort(nick2);
                    s.close();
                    break;
                default:
                    s.close();            
            }
        }
        catch(IOException e)
        {
            System.out.println("Fehler bei Abmeldung");             
        }
    }
    
    public ServerSocket getSocket()
    {
        return hatServerSocket;
    }
    
    public void gibPort()
    {
        switch(teilnehmerzahl)
        {
            case(1):
                ip1 = teilnehmerliste.gibIP(nick1);
                p1 = teilnehmerliste.gibPort(nick1);
                break;
            case(2):
                ip1 = teilnehmerliste.gibIP(nick1);
                p1 = teilnehmerliste.gibPort(nick1);
                ip2 = teilnehmerliste.gibIP(nick2);
                p2 = teilnehmerliste.gibPort(nick2);
                break;        
        }
    }    
    // Ende Ereignisprozeduren
}
```

ure Hilfe zählen. 

GUIServer


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

/**
  *
  * @version 1.0 vom 14.01.2014
  * 
  * @author Jonas Lampe 
  * 
  */

public class GUIServer extends Frame 
{
  private   EchoServer      es;
  private   JButton         bNeu            = new JButton();
  private   JButton         bStarten        = new JButton();
  private   JLabel          jPort           = new JLabel();
  private   JTextField      jtPort          = new JTextField();
  private   JScrollPane     jspjtaLog       = new JScrollPane();
  public    JTextArea       jtaLog          = new JTextArea("");
  private   boolean         b;
  private   boolean         c;
  // Ende Attribute  
  
  
  public GUIServer(String title) 
  { 
      
    // Frame-Initialisierung
    super(title);
    addWindowListener(new WindowAdapter() 
    {
        public void windowClosing(WindowEvent evt) 
        { 
            dispose(); 
        }
    });
    
    
    int frameWidth = 400; 
    int frameHeight = 405;
    setSize(frameWidth, frameHeight);
    
    
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2;
    setLocation(x, y);
    
    
    setResizable(false);
    setVisible(true);
    
    
    // Anfang Komponenten
    Panel cp = new Panel(null);
    add(cp);

    bNeu.setBounds(160, 330, 80, 25);
    bNeu.setText("Neues Spiel");
    bNeu.setMargin(new Insets(2, 2, 2, 2));
    cp.add(bNeu);
    bNeu.addActionListener(new ActionListener() 
    { 
        public void actionPerformed(ActionEvent evt)
        { 
            bNeu_ActionPerformed(evt);
        }
    });
    
    
    bStarten.setBounds(32, 24, 161, 58);
    bStarten.setText("Server starten...");
    bStarten.setMargin(new Insets(2, 2, 2, 2));
    cp.add(bStarten);
    bStarten.addActionListener(new ActionListener() 
    { 
        public void actionPerformed(ActionEvent evt)
        { 
            bStarten_ActionPerformed(evt);
        }
    });
    
    jPort.setBounds(235, 40, 102, 25);
    jPort.setText("Port:");
    cp.add(jPort);
    jtPort.addFocusListener(new java.awt.event.FocusAdapter() 
    {
        public void focusGained(java.awt.event.FocusEvent evt) 
        {
            if(jtPort.getText().equals("Port eingeben"))
                jtPort.setText("");
        }
    });
    
    
    jtPort.setBounds(267, 40, 105, 25);
    jtPort.setText("Port eingeben");
    cp.add(jtPort);

    
    jspjtaLog.setBounds(75, 110, 250, 200);;
    jtaLog.setText("\n");
    jspjtaLog.setViewportView(jtaLog);
    cp.add(jspjtaLog);
    
    // Ende Komponenten
    
    b = false;
    c = false;
    
  } // end of public GUIServer
  
  
  // Anfang Methoden
  public void bNeu_ActionPerformed(ActionEvent evt) 
  {
      es.sendToAll("NEU"); 
  } //end of bNeu_ActionPerformed
  
  
  public void bStarten_ActionPerformed(ActionEvent evt) 
  {
      String s = "Server trennen...";
      if(jtPort.getText() != "" && isInteger() == true)
      {
          if (b == false) 
          {
              bStarten.setText("Server trennen...");
              es = new EchoServer(Integer.parseInt(jtPort.getText()),jtaLog, this);
              b = true;   
          } 
          else
          {
              bStarten.setText("Server starten...");
              es.closeSocket(es.getSocket());
              //Server.ServerSchleife.b = false;
              b = false;
          }
       }
       else
    {
        if(s == bStarten.getText())
        {
            bStarten.setText("Server starten...");
            es.closeSocket(es.getSocket());
            //Server.ServerSchleife.b = false;
            b = false;
        }
        else
        {
            jtaLog.setText("Bitte gebe einen gültigen Port ein.");
        }
    }
  } // end of bStarten_ActionPerformed
  
  
  public static void main(String[] args) 
  {
      new GUIServer("GUIServer");
  } // end of main
  
  
  public boolean isInteger() 
  {
    try 
    { 
        Integer.parseInt(jtPort.getText()); 
    } 
    catch(NumberFormatException e) 
    { 
        return false; 
    }
    // only got here if we didn't return false
    return true;
  }
  public void port()
  {
      es.gibPort();
  }
  
} // end of class GUIServer
```

TeilnehmerListe


```
/**
  *
  * Beschreibung
  *
  * @version 1.0 vom 24.03.2009
  * @author
  */

public class TeilnehmerListe {

  // Anfang Variablen
  private List liste;
  // Ende Variablen

  public TeilnehmerListe() {
    liste = new List();
  }

  // Anfang Ereignisprozeduren
  public boolean hinzufuegen(String ip, int port, String nick) {
    Teilnehmer teilnehmer = new Teilnehmer(ip, port, nick);
    if (gibPort(nick) == -1) {
      liste.toLast();
      liste.insertBehind(teilnehmer);
      liste.next();
      return true;
    } else {
      return false;
    }
  }

  public boolean entfernen(String nick) {
    if (this.gibPort(nick) != -1) {
      liste.remove();
      return true;
    } else {
      return false;
    }
  }
  
  public boolean entfernen(String ip, int port) {
    if (this.gibName(ip, port) != null) {
      liste.remove();
      return true;
    } else {
      return false;
    }
  }

  public String gibIP(String name) {
    for (liste.toFirst(); !liste.isBehind(); liste.next()) {
      if (((Teilnehmer)liste.getItem()).gibName().equals(name))
        return ((Teilnehmer)liste.getItem()).gibIP();
    }
    return null;
  }

  public int gibPort(String name) {
    for (liste.toFirst(); !liste.isBehind(); liste.next()) {
      if (((Teilnehmer)liste.getItem()).gibName().equals(name))
        return ((Teilnehmer)liste.getItem()).gibPort();
    }
    return -1;
  }

  public String gibName(String ip, int port) {
    for (liste.toFirst(); !liste.isBehind(); liste.next()) {
      if (((Teilnehmer)liste.getItem()).gibIP().equals(ip) &&
          ((Teilnehmer)liste.getItem()).gibPort() == port)
        return ((Teilnehmer)liste.getItem()).gibName();
    }
    return null;
  }

  public String gibAlleNamen() {
    String s = "";
    for (liste.toFirst(); !liste.isBehind(); liste.next()) {
      s = s + ((Teilnehmer)liste.getItem()).gibName()+ ",";
    }
    s = s.substring(0,s.length()-1);
    return s;
  }
  public boolean Empty()
  {
      return liste.isEmpty();
  }
  // Ende Ereignisprozeduren
}
```

Teilnehmer


```
/**
  *
  * Beschreibung
  *
  * @version 1.0 vom 24.03.2009
  * @author
  */

public class Teilnehmer {

  // Anfang Variablen
  private String ip;
  private int port;
  private String name;
  // Ende Variablen

  public Teilnehmer(String ip, int port, String name) {
    this.name = name;
    this.ip = ip;
    this.port = port;
  }

  // Anfang Ereignisprozeduren


  public String gibIP() {
    return ip;
  }


  public int gibPort() {
    return port;
  }


  public String gibName() {
    return name;
  }


  // Ende Ereignisprozeduren
}
```


----------



## jonas.to.go (22. Jan 2014)

Sorry das es so viel ist, aber hier der letzte Teil:

List


```
/**
 * Klasse für eine Liste nach Zentralabitur.
 * Am Anfang und am Ende der Liste sind zwei leere Elemente.
 * @author Daniel Garmann
 * @version 18.08.2008
 */
public class List {
  private Element pAnfang;
  private Element pEnde;
  private Element pAktuell;

  /**
   *  Konstruktor create
   *  Nachher: Eine leere Liste ist angelegt. Der interne Positionszeiger steht
   *           vor der leeren Liste
   */
  public List() {
    pAnfang = new Element(null, null, null);
    pEnde = new Element(null, pAnfang, null);
    pAktuell = pAnfang;
    pAnfang.setNext(pEnde);
  }

  private void connectNodes(Element pLNode, Element pRNode) {
    pLNode.setNext(pRNode);
    pRNode.setPrev(pLNode);
  }

  /**
   *  Anfrage isEmpty: boolean
   *  Nachher: Die Anfrage liefert den Wert true, wenn die Liste keine Elemente
   *           enthält, sonst liefert sie den Wert false.
   */
  public boolean isEmpty() {
    return pAnfang.next() == pEnde;
  }

  /**
   *  Anfrage isInFrontOf : boolean
   *  Nachher: Die Anfrage liefert den Wert true, wenn der Positionszeiger
   *           vor dem ersten Listenelement oder vor der leeren Liste steht,
   *           sonst liefert sie den Wert false.
   */
  public boolean isInFrontOf() {
    return pAktuell == pAnfang;
  }

  /**
   *  Anfrage isBehind: boolean
   *  Nachher: Die Anfrage liefert den Wert true, wenn der Positionszeiger
   *           hinter dem letzten Listenelement oder hinter der leeren Liste steht,
   *           sonst liefert sie den Wert false.
   */
  public boolean isBehind() {
    return pAktuell == pEnde;
  }

  /**
   *  Auftrag next
   *  Nachher: Der Positionszeiger ist um eine Position in Richtung Listenende
   *           weitergerückt, d.h. wenn er vor der Liste stand, wird das Element
   *           am Listenanfang zum aktuellen Element, ansonsten das jeweils
   *           nachfolgende Listenelement.
   *           Stand der Positionszeiger auf dem letzten Listenelement, befindet
   *           er sich jetzt hinter der Liste. Befand er sich hinter der Liste,
   *           hat er sich nicht verändert.
   */
  public void next() {
    if (!this.isBehind()) {
      pAktuell = pAktuell.next();
    }
  }

  /**
   *  Auftrag previous
   *  Nachher: Der Positionszeiger ist um eine Position in Richtung Listenanfang
   *          weitergerückt, d.h. wenn er hinter der Liste stand, wird das Element
   *          am Listenende zum aktuellen Element, ansonsten das jeweils
   *          vorhergehende Listenelement.
   *          Stand der Positionszeiger auf dem ersten Listenelement, befindet er
   *          sich jetzt vor der Liste. Befand er sich vor der Liste,
   *          hat er sich nicht verändert.
   */
  public void previous() {
    if (!this.isInFrontOf()) {
      pAktuell = pAktuell.prev();
    }
  }

  /**
   * Auftrag toFirst
   * Nachher: Der Positionszeiger steht auf dem ersten Listenelement. Falls die
   *          Liste leer ist, befindet er sich jetzt hinter der Liste.
   */
  public void toFirst() {
    pAktuell = pAnfang.next();
  }

  /**
   * Auftrag toLast
   * Nachher: Der Positionszeiger steht auf dem letzten Listenelement. Falls
   *          die Liste leer ist, befindet er sich jetzt vor der Liste.
   */
  public void toLast() {
    pAktuell = pEnde.prev();
  }

  /**
   * Anfrage getItem: Object
   * Nachher: Die Anfrage liefert den Wert des aktuellen Listenelements bzw.
   *          nil, wenn die Liste keine Elemente enthält oder der Positionszeiger
   *          vor oder hinter der Liste steht.
   */
  public Object getItem() {
    return pAktuell.content();
  }

  /**
   * Auftrag replace (pObject: Object)
   * Vorher:  Die Liste ist nicht leer. Der Positionszeiger steht nicht vor oder
   *          hinter der Liste.
   * Nachher: Der Wert des Listenelements an der aktuellen Position ist durch
   *          pObject ersetzt.
   */
  public void replace(Object pContent) {
    if (!(this.isInFrontOf() || this.isBehind())) {
      pAktuell.setContent(pContent);
    }
  }

  /**
   * Auftrag insertBefore (pObject:Object)
   * Vorher:  Der Positionszeiger steht nicht vor der Liste.
   * Nachher: Ein neues Listenelement mit dem entsprechenden Objekt ist angelegt
   *          und vor der aktuellen Position in die Liste eingefügt worden.
   *          Der Positionszeiger steht hinter dem eingefügten Element.
   */
  public void insertInFrontOf(Object pContent) {
    Element lNewNode;

    if (this.isInFrontOf()) {
      this.next();
    }

    lNewNode = new Element(pContent, pAktuell.prev(), pAktuell);
    pAktuell.prev().setNext(lNewNode);
    pAktuell.setPrev(lNewNode);
  }

  /**
   * Auftrag insertBehind (pObject: Object)
   * Vorher:  Der Positionszeiger steht nicht hinter der Liste.
   * Nachher: Ein neues Listenelement mit dem entsprechenden Objekt ist angelegt
   *          und hinter der aktuellen Position in die Liste eingefügt worden.
   *          Der Positionszeiger steht vor dem eingefügten Element.
   */
  public void insertBehind(Object pContent) {
    Element lNewNode;

    if (this.isBehind()) {
      this.previous();
    }

    lNewNode = new Element(pContent, pAktuell, pAktuell.next());
    pAktuell.next().setPrev(lNewNode);
    pAktuell.setNext(lNewNode);
  }

  /**
   * Auftrag remove
   * Vorher:  Der Positionszeiger steht nicht vor oder hinter der Liste.
   * Nachher: Das aktuelle Listenelement ist gelöscht. Der Positionszeiger steht
   *          auf dem Element hinter dem gelöschten Element, bzw. hinter der
   *          Liste, wenn das gelöschte Element das letzte Listenelement war.
   *          Das Inhaltsobjekt des gelöschten Listenelements existiert weiterhin.
   */
  public void remove() {
    if (!(this.isInFrontOf() || this.isBehind())) {
      this.connectNodes(pAktuell.prev(), pAktuell.next());
      pAktuell = pAktuell.next();
    }
  }

  /**
   * Auftrag addList(pList: List)
   * Nachher: Die Liste pList ist der Liste angefügt. Die übergebene
   *          Listenstruktur von pList existiert nicht mehr.
   */
  public void addList(List pList) {
    Element lCurrent1;
    Element lCurrent2;

    if (!pList.isEmpty()) {
      this.toLast();
      lCurrent1 = this.pAktuell;
      pList.toFirst();
      lCurrent2 = pList.pAktuell;
      this.connectNodes(lCurrent1, lCurrent2);
      this.pEnde = pList.pEnde;
      pList = new List();
    }
  }

  /**
   * Destruktor destroy
   * Nachher: Die Liste existiert nicht mehr
   */
  public void free() {
    while (!this.isEmpty()) {
      this.toFirst();
      this.remove();
    }
  }
}
```

Element


```
/**
 * Klasse für einen Knoten einer Liste nach Zentralabitur
 * @author Daniel Garmann
 * @version 18.08.2008
 */
public class Element {
  private Object kContent;
  private Element kPrev;
  private Element kNext;

  /**
   * Konstruktor
   */
  public Element(Object pContent, Element pPrev, Element pNext) {
    kContent = pContent;
    kPrev = pPrev;
    kNext = pNext;
  }

  /**
   * Setter für den Inhalt
   */
  public void setContent(Object pContent) {
    kContent = pContent;
  }

  /**
   * Getter für den Inhalt
   */
  public Object content() {
    return kContent;
  }

  /**
   * Setter für den Nachfolger
   */
  public void setNext(Element pNext) {
    kNext = pNext;
  }

  /**
   * Getter für den Nachfolger
   */
  public Element next() {
    return kNext;
  }

  /**
   * Setter für den Vorgänger
   */
  public void setPrev(Element pPrev) {
    kPrev = pPrev;
  }

  /**
   * Getter für den Vorgänger
   */
  public Element prev() {
    return kPrev;
  }
}
```

Regeln


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Rules extends JFrame
{
    private     JButton     bExit       = new JButton();
    private     JLabel      jRules      = new JLabel();
    private     JLabel      jtitle      = new JLabel();
    
    public Rules(String title)
    {
        super(title);
        addWindowListener(new WindowAdapter() 
        {
            public void windowClosing(WindowEvent evt) 
            { 
                dispose(); 
            }
        });
        
        int frameWidth = 250; 
        int frameHeight = 320;
        setSize(frameWidth, frameHeight);
        
        
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 2;
        int y = (d.height - getSize().height) / 2;
        setLocation(x, y);
        
        
        setResizable(false);        
        setVisible(true);
        
        
        // Anfang Komponenten
        Panel cp = new Panel(null);
        add(cp);
        
        
        bExit.setBounds(90, 230, 65, 25);
        bExit.setText("Exit");
        bExit.setMargin(new Insets(2, 2, 2, 2));
        cp.add(bExit);
        bExit.addActionListener(new ActionListener() 
        { 
            public void actionPerformed(ActionEvent evt) 
            { 
                bExit_ActionPerformed(evt);
            }
        });
        
        
        jRules.setBounds(45, 30, 200, 200);
        jRules.setText("<html><head><title>Regeln zu TbbT-Schnick-Schnack-Schnuck</title></head><body><p>Schere schneidet Papier</p><p>Papier bedeckt Stein</p><p>Stein zerquetscht Echse</p><p>Echse vergiftet Spock \n <p>Spock zertrümmert Schere</p><p>Schere köpft Echse</p><p>Echse frisst Papier</p><p>Papier widerlegt Spock</p><p>Spock verdampft Stein</p><p>Stein schleift Schere</body></html> ");
        cp.add(jRules);
        
        
        jtitle.setBounds(22, 15, 200, 25);
        jtitle.setText("Regeln für TbbT-ChingChangChong");
        jtitle.setFont(jtitle.getFont().deriveFont(Font.BOLD));
        cp.add(jtitle);
    }
    
    
    
    public void bExit_ActionPerformed(ActionEvent evt)
    {
        dispose();
    }
}
```


Meine Probleme liegen jetzt noch beim Server trennen, sodass ein verbundener Client gleichzeitig von Server fliegtund wenn kein Client verbunden ist, er den Server trotzdem trennt und den Socket wieder freigibt.
Ein paar Exception sind noch nicht abgefangen, aber das mache ich zum Schluss.
Ich weiß auch selber, dass das ganze viel einfacher geht aber unser Lehrer möchte gerne eine viel zu umständliche Version (hab damit schon Erfahrung gesammelt (hab ne 4 für nen Programm bekommen, weil ich es einfacher gemacht hatte als der Lehrer)).

Ich weiß, dass das viel Code ist, aber ich bin hier nach 5 Stunden an dem selben Problem langsam am verzweifeln und würde jetzt mal auf eure Hilfe zählen.


----------

