eine Serverklasse

?

Wie findet ihr das?

  1. Sehr gut

    0 Stimme(n)
    0,0%
  2. gut

    0 Stimme(n)
    0,0%
  3. geht so

    0 Stimme(n)
    0,0%
  4. nicht so gut

    0 Stimme(n)
    0,0%
  5. schlecht

    0 Stimme(n)
    0,0%

Diskutiere eine Serverklasse im Codeschnipsel u. Projekte Forum; Hallo, ich habe mal eine Klasse geschrieben, mit der man ganz einfach einen Server erstellen kann und Strings empfangen und verschicken kann....

  1. PhysischePhysik
    PhysischePhysik Neues Mitglied
    Hallo,
    ich habe mal eine Klasse geschrieben,
    mit der man ganz einfach einen Server erstellen kann und Strings empfangen und verschicken kann.

    Code (Java):

    package chat.server.api;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;

    public abstract class EasyServer {
        private ServerSocket server;
        private int count = 0;
        private Map<Integer, Socket> clients = new ConcurrentHashMap<>();
        private Map<Socket, PrintWriter> outs = new ConcurrentHashMap<>();
        private Map<Integer, InetAddress> ips = new ConcurrentHashMap<>();

        public EasyServer(int port) throws NetworkException {
            try {
                server = new ServerSocket(port);
                new Thread(this::accept).start();
            } catch (IOException ex) {
                throw new Exception("Konnte Server nicht starten", ex);
            }
        }

        private void accept() {
            try {
                while (server.isBound()) {
                    Socket client = server.accept();
                    count++;
                    clients.put(count, client);
                    outs.put(client, new PrintWriter(client.getOutputStream(), true));
                    ips.put(count, client.getInetAddress());
                    new Thread(() -> handle(client, count)).start();
                }
            } catch (IOException ex) {
                if(!server.isClosed()) {
                    new Exception("Fehler beim akzeptieren von Clients", ex).printStackTrace();
                }
            }
        }

        protected void close() {
            try {
                server.close();
            } catch (IOException ignored) {}
        }

        protected void disconnect(int id) {
            Socket client = clients.get(id);
            if(client != null) {
                try {
                    client.close();
                } catch (IOException ignored) {}
            }
        }

        protected void disconnectAll() {
            List<Socket> list = new ArrayList<>(clients.values());
            int i = 0;
            while (i < list.size()) {
                Socket client = list.get(i);
                try {
                    client.close();
                } catch (IOException ignored) {}
                i++;
            }
        }

        private void handle(Socket client, int id) {
            try {
                join(id);
                BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                String s;
                while((s = in.readLine()) != null) {
                    income(s, id);
                }
            } catch (IOException ignored) {}
            try {
                client.close();
            } catch (IOException ignored) {}
            clients.remove(id);
            outs.remove(client);
            quit(id);
        }

        protected void broadcast(String msg) {
            List<PrintWriter> list = new ArrayList<>(outs.values());
            int i = 0;
            while (i < list.size()) {
                PrintWriter out = list.get(i);
                out.println(msg);
                i++;
            }
        }

        protected InetAddress getIp(int id) {
            return ips.get(id);
        }

        protected void send(int id, String msg) {
            Socket client = clients.get(id);
            if(client != null) {
                PrintWriter out = outs.get(client);
                out.println(msg);
            }
        }

        protected abstract void income(String msg, int id);

        protected abstract void quit(int id);

        protected abstract void join(int id);

    }
     
    Man muss von dieser Klasse erben, da beim Verbinden, Verbindung trennen und wenn eine Nachricht eingeht, eine abstrakte Methode aufgerufen wird.

    Beim Konstruktor muss man den Port übergeben, und dann wird der Server gestartet.
    Wenn beim Starten vom Server etwas schief läuft, wird eine Exception geworfen und die IOException vom ServerSocket Konstruktor bei der Exception als Ursache mit übergeben.

    Wenn ein Client sich verbindet, wird die
    Code (Java):
    join(int id)
    Methode aufgerufen.
    Jeder Client bekommt eine ID.

    Wenn ein Client ein String sendet wird die
    Code (Java):
    income(String msg, int id)
    Methode aufgerufen.
    Code (Java):
    msg
    ist der String, den der Client sendet.

    mit
    Code (Java):
    send(int id, String msg)
    schickt man einem Client einen String.

    mit
    Code (Java):
    broadcast(String msg)
    schickt man einen String an alle Clients.

    mit
    Code (Java):
    getIp(int id)
    bekommt man die IP Adresse eines Clients.

    mit der
    Code (Java):
    disconnect(int id)
    Methode kann man eine Verbindung von einem Client trennen.

    mit
    Code (Java):
    disconnectAll()
    werden alle Client Verbindungen getrennt.

    mit
    Code (Java):
    close()
    schließt man den Server, alle Client Verbindungen bleiben allerdings bestehen.

    Beispiel:
    Code (Java):

    package chat.server.api;

    public class ServerTest extends EasyServer {

        public static void main(String[] args) {
            try {
                new ServerTest(1234);
            } catch (Exception e) {
                System.err.println("Da ist was schiefgelaufen...");
                e.printStackTrace();
            }
        }

        public ServerTest(int port) throws Exception {
            super(port);
        }

        @Override
        protected void income(String msg, int id) {
            broadcast(id + ": " + msg);
            if(msg.equals("CLOSE")) {
                close();
            }
            if(msg.equals("DISCONNECT")) {
                disconnect(id);
            }
            if(msg.equals("DISCONNECTALL")) {
                disconnectAll();
            }
            if(msg.equals("IP")) {
                send(id, getIp(id).toString());
            }
        }

        @Override
        protected void quit(int id) {
            broadcast("[-" + id + "]");
        }

        @Override
        protected void join(int id) {
            broadcast("[+" + id + "]");
        }
    }
     
    Währe nett, wenn ihr mir Feedback gebt und evt. Verbesserungsvorschläge.
     
  2. Vielleicht hilft dir dieser Kurs hier weiter (Klick!)
  3. PhysischePhysik
    PhysischePhysik Neues Mitglied
    Hab eine Methode vergessen:
    die
    Code (Java):
    quit(int id)
    Methode wird aufgerufen, wenn ein Client die Verbindung trennt.
     
  4. mrBrown
    mrBrown Bekanntes Mitglied
    Ohne speziellen Bezug zum Thema Server:

    * Deine ganzen Erklärungen solltest du als Javadoc in der Klasse unterbringen.
    * send und income erwarten die Parameter in umgekehrter Reihenfolge, das ist etwas verwirrend.
    * Ähnlich wie bei Thread und Runnable würde ich die abstrakten Methoden in ein Interface auslagern und das dem Thread zusätzlich übergebbar machen. Dann hat man die Wahl, ob man das Interface übergibt, oder die Klasse extendet
    * bis auf income würde ich für die abstrakten Methoden eine default-Implementierung bereitstellen, die einfach nichts machen
    * count würde ich anders nennen - vom Namen her würde man da die Anzahl, und nicht die nächste ID erwarten
    * deine while-Schleifen würde ich mindestens mit fort-schleifen ersetzen, besser aber mit for-each
    * Kompiliert das ganze überhaupt? throws des Konstruktors stimmt nicht mit der geworfenen überein
    * Exception würde ich niemals direkt werfen, immer eine passende.
    * in accept die Exception nur zum loggen erstellen ist nicht der beste Stil, stattdessen einfach gefangene mit eigener Nachricht loggen
    * die ganzen ignorierten würde ich auch loggen
     
    PhysischePhysik gefällt das.
  5. PhysischePhysik
    PhysischePhysik Neues Mitglied
    EDIT:
    Habe vergessen beim Konstruktor bei throws die NetworkException in Exception umzuändern.
    Ich habe bei mir noch eine NetworkException die ich stattdessen immer werfe, die ich hier aber weggelassen habe, aber habe vergessen das bei throws hier zu ändern.
     
  6. mrBrown
    mrBrown Bekanntes Mitglied
    Da wäre btw deutlich besser als nur Exception ;)
     
    PhysischePhysik gefällt das.

Die Seite wird geladen...

eine Serverklasse - Ähnliche Themen

While-Schleife in einem Service für GUI
While-Schleife in einem Service für GUI im Forum AWT, Swing, JavaFX & SWT
Nach dem Herüberschieben eines Arrays zwischen 2 Frames öffnet sich das Frame nicht mehr
Nach dem Herüberschieben eines Arrays zwischen 2 Frames öffnet sich das Frame nicht mehr im Forum Java Basics - Anfänger-Themen
Attribut einer anderen Klasse übertragen/verwenden
Attribut einer anderen Klasse übertragen/verwenden im Forum Java Basics - Anfänger-Themen
Selektion aus einer ListView
Selektion aus einer ListView im Forum AWT, Swing, JavaFX & SWT
Wieso wird nur ein Teil meiner Buttons angezeigt?
Wieso wird nur ein Teil meiner Buttons angezeigt? im Forum AWT, Swing, JavaFX & SWT
Thema: eine Serverklasse