Chatserver/-client - Code stoppt bei readUTF()

Avo_MODE

Mitglied
Hallo erstmal.

Wie im Titel erwähnt, arbeite ich an einem Programm, das einen ChatServer und ChatClient enthält.
Ich habe bei meinen "Problemzeilen" folgenden Code gesetzt, damit ich weiß, wann der Code aufhört.
Java:
System.out.println("1");
String line = streamIn.readUTF(); < Fehler
System.out.println("2"); < das wird nicht mehr in der Konsole ausgegeben
...

Ich habe 2 Projekte, ChatClient und ChatServer.
Klassen:
ChatClient:
- Client.java
- ClientGUI.java
ChatServer:
- Server.java
- ServerGUI.java
- ServerClient.java

Achtet bei eurer Antwort darauf, mein Problem zu lösen und nicht mich auf meiner komplizierten Weise meines Codes zuzuweißen (Threads, Timers, etc.).

Hier die Codes:
Client.java (enthält den Fehler)
Java:
package me.avo.chat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JEditorPane;

public class Client {

    private Socket socket = null;
    private DataOutputStream streamOut = null;
    private DataInputStream streamIn = null;

    private String clientName = "";

    public Client(String clientName, String serverName, int serverPort) {
        this.clientName = clientName;
        try {
            socket = new Socket(serverName, serverPort);
            start();
        } catch (UnknownHostException uhe) {
            System.out.println("Host unknown: " + uhe.getMessage());
        } catch (IOException ioe) {
            System.out.println("Unexpected exception: " + ioe.getMessage());
        }
    }

    public DataInputStream getInputStream() {
        return streamIn;
    }

    public void handleChat(final JEditorPane dtrpnLogs) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Running");
                try {
                    try {
                        String line = streamIn.readUTF();
                        System.out.println("Received message");
                        dtrpnLogs.setText(dtrpnLogs.getText() + "\n" + line);
                    } catch (EOFException ex) {
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }

    public void sendMessage(String message) {
        try {
            System.out.println("Sending \"" + this.clientName + "> " + message + "\"");
            streamOut.writeUTF(this.clientName + ": " + message);
            streamOut.flush();
            System.out.println("Sent to streamOut");
        } catch (IOException ioe) {
            System.out.println("Sending error: " + ioe.getMessage());
        }
    }

    public void start() throws IOException {
        streamIn = new DataInputStream(socket.getInputStream());
        streamOut = new DataOutputStream(socket.getOutputStream());
    }

    public void stop() {
        try {
            if (streamIn != null)
                streamIn.close();
            if (streamOut != null)
                streamOut.close();
            if (socket != null)
                socket.close();
        } catch (IOException ioe) {
            System.out.println("Error closing ...");
        }
    }

}

ClientGUI.java
Java:
package me.avo.chat;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;

public class ClientGUI {

    private JFrame frame;
    private JTextField textField;
    private JTextField textField_1;
    private JTextField message;
    private Client client;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ClientGUI window = new ClientGUI();
                    window.frame.setVisible(true);
                    window.frame.setTitle("ChatClient");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public ClientGUI() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 425, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        JLabel lblHostname = new JLabel("Hostname");
        lblHostname.setBounds(10, 11, 56, 14);
        frame.getContentPane().add(lblHostname);

        JLabel lblPort = new JLabel("Port");
        lblPort.setBounds(106, 11, 46, 14);
        frame.getContentPane().add(lblPort);

        JLabel lblUsername = new JLabel("Username");
        lblUsername.setBounds(186, 11, 56, 14);
        frame.getContentPane().add(lblUsername);

        textField = new JTextField();
        textField.setBounds(10, 30, 86, 20);
        frame.getContentPane().add(textField);
        textField.setColumns(10);

        final JSpinner spinner = new JSpinner();
        spinner.setBounds(106, 30, 70, 20);
        frame.getContentPane().add(spinner);

        textField_1 = new JTextField();
        textField_1.setBounds(186, 30, 86, 20);
        frame.getContentPane().add(textField_1);
        textField_1.setColumns(10);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 61, 389, 242);
        frame.getContentPane().add(scrollPane);

        final JEditorPane dtrpnLogs = new JEditorPane();
        dtrpnLogs.setText("Logs");
        scrollPane.setViewportView(dtrpnLogs);

        final JButton btnLogin = new JButton("Login");
        btnLogin.setBounds(282, 29, 117, 23);
        btnLogin.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                btnLogin.setEnabled(false);
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        client = new Client(textField_1.getText(), textField.getText(),
                                Integer.parseInt(String.valueOf(spinner.getValue())));
                        try {
                            client.start();
                            btnLogin.setText("Logged in");
                            Timer timer = new Timer();
                            timer.scheduleAtFixedRate(new TimerTask() {
                                @Override
                                public void run() {
                                    client.handleChat(dtrpnLogs);
                                }
                            }, 1000, 1000);
                        } catch (IOException e1) {
                            btnLogin.setEnabled(true);
                            e1.printStackTrace();
                        }
                    }
                });
                thread.start();
            }
        });
        frame.getContentPane().add(btnLogin);

        message = new JTextField();
        message.setBounds(10, 314, 250, 39);
        frame.getContentPane().add(message);
        message.setColumns(10);

        JButton btnSend = new JButton("Send Message");
        btnSend.setBounds(270, 314, 129, 39);
        btnSend.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Sending message..");
                client.sendMessage(message.getText());
                message.setText("");
                System.out.println("Message sent!");
            }
        });
        frame.getContentPane().add(btnSend);
    }

}

Server.java
Java:
package me.avo.chat;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

public class Server {

    private ServerSocket server;

    private ArrayList<ServerClient> connectedClients = new ArrayList<>();

    private int port;

    private Server(int port) {
        this.port = port;
    }

    public static Server newServer(int port) {
        return new Server(port);
    }

    public ArrayList<ServerClient> getConnectedClients() {
        return connectedClients;
    }

    public void sendToAll(String line) {
        try {
            for (ServerClient ss : connectedClients) {
                if (!ss.isConnected()) {
                    connectedClients.remove(ss);
                    System.out.println("Couldn't send to " + ss.getSocket());
                    continue;
                }
                ss.sendMessage(line);
                System.out.println("Sent to " + ss.getSocket());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void waitForClients() {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Runned timer");
                try {
                    Socket socket = server.accept();
                    final ServerClient client = new ServerClient(socket);
                    if (client != null) {
                        ServerGUI.getLogPane().setText(
                                ServerGUI.getLogPane().getText() + "\nClient connected: " + client.getSocket());
                        Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                client.chatHandle();
                            }
                        });
                        thread.start();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }, 1000, 1000);
    }

    public boolean start() {
        try {
            server = new ServerSocket(port);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

}

ServerGUI.java
Java:
package me.avo.chat;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;

public class ServerGUI {

    private JFrame frmChatserver;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ServerGUI window = new ServerGUI();
                    window.frmChatserver.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public ServerGUI() {
        initialize();
    }

    private static JEditorPane dtrpnLogs;

    private static Server pbl_server;

    public static JEditorPane getLogPane() {
        return dtrpnLogs;
    }

    public static Server getServer() {
        return pbl_server;
    }

    private void initialize() {
        frmChatserver = new JFrame();
        frmChatserver.setTitle("ChatServer");
        frmChatserver.setBounds(100, 100, 450, 400);
        frmChatserver.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmChatserver.getContentPane().setLayout(null);

        JLabel lblPort = new JLabel("Port");
        lblPort.setBounds(10, 11, 46, 14);
        frmChatserver.getContentPane().add(lblPort);

        final JSpinner txtPort = new JSpinner();
        txtPort.setBounds(66, 8, 86, 20);
        frmChatserver.getContentPane().add(txtPort);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 36, 414, 317);
        frmChatserver.getContentPane().add(scrollPane);

        dtrpnLogs = new JEditorPane();
        dtrpnLogs.setText("Logs");
        scrollPane.setViewportView(dtrpnLogs);

        final JButton btnStartChatserver = new JButton("Start Chatserver");
        btnStartChatserver.setBounds(162, 7, 262, 23);
        btnStartChatserver.addActionListener(new ActionListener() {
            Thread thread;

            @SuppressWarnings("deprecation")
            @Override
            public void actionPerformed(ActionEvent e) {
                if (btnStartChatserver.getText().equals("Start Chatserver")) {
                    btnStartChatserver.setText("Stop Chatserver");
                    final int port = (int) txtPort.getValue();
                    thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            final Server server = Server.newServer(port);
                            server.start();
                            pbl_server = server;
                            dtrpnLogs.setText(dtrpnLogs.getText() + "\nServer started at port " + port);
                            Thread waitFor = new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    server.waitForClients();
                                }
                            });
                            waitFor.start();
                        }
                    });
                    thread.start();
                } else {
                    btnStartChatserver.setText("Start Chatserver");
                    if (thread != null)
                        thread.stop();
                    dtrpnLogs.setText(dtrpnLogs.getText() + "\nServer stopped");
                }
            }
        });
        frmChatserver.getContentPane().add(btnStartChatserver);
    }
}

ServerClient.java
Java:
package me.avo.chat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

public class ServerClient {

    private Socket socket;
    private DataInputStream in;
    private DataOutputStream out;

    public ServerClient(Socket socket) throws IOException {
        this.socket = socket;
        in = new DataInputStream(socket.getInputStream());
        out = new DataOutputStream(socket.getOutputStream());
    }

    public Socket getSocket() {
        return socket;
    }

    public DataOutputStream getOutputStream() {
        return out;
    }

    public DataInputStream getInputStream() {
        return in;
    }

    public boolean isConnected() {
        return !(socket.isClosed());
    }

    public void chatHandle() {
        Timer chat_connectClient = new Timer();
        chat_connectClient.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Runned chathandler");
                try {
                    DataInputStream in = getInputStream();
                    String line = null;
                    boolean hasNext = false;
                    try {
                        line = in.readUTF();
                        hasNext = true;
                    } catch (EOFException ex) {
                        line = null;
                        hasNext = false;
                    }
                    if (hasNext) {
                        System.out.println("Received \"" + line + "\"");
                        ServerGUI.getServer().sendToAll(line);
                        ServerGUI.getLogPane().setText(ServerGUI.getLogPane().getText() + "\nLogged message: " + line);
                        System.out.println("Message connected to Clients!");
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }, 1000, 1000);
    }

    public void sendMessage(String line) {
        try {
            out.writeUTF(line);
            out.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public ArrayList<String> getMessages() {
        try {
            ArrayList<String> messages = new ArrayList<>();
            for (int i = 0; i <= in.available(); i++) {
                messages.add(in.readUTF());
            }
            return messages;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return null;
    }

}

Ich bin für jede Art von Hilfe dankbar.

LG
Avo
 

Avo_MODE

Mitglied
(Ich kann das Thema nicht editieren, deshalb schreibe ich es mal als Antwort)

Mir ist aufgefallen, dass ich das Problem nicht beschrieben habe.

Code (Java): System.out.println("1");
String line = streamIn.readUTF(); < Fehler
System.out.println("2"); < das wird nicht mehr in der Konsole ausgegeben
...
Der markierte Bereich "< Fehler" zeigt die Zeile, indem der Code nicht mehr weitergeht. Hier soll die Chat-Nachricht gelesen werden. Diese wird NUR im Server-Log gesendet, wird aber nicht den einzelnen Clients zugesendet.

Screenshot:
141901535a0b2f91b09fa.png
 

VfL_Freak

Top Contributor
Moin,
Achtet bei eurer Antwort darauf, mein Problem zu lösen und nicht mich auf meiner komplizierten Weise meines Codes zuzuweißen (Threads, Timers, etc.).
ich werde mich hüten ..... :cool:

dann:
System.out.println("1");
String line = streamIn.readUTF(); < Fehler
System.out.println("2"); < das wird nicht mehr in der Konsole ausgegeben
Wo genau im Code tritt das auf rsp. WO ist diese Zeile?
Aber viel wichtiger: WELCHER Fehler kommt denn?
Poste mal den kompletten StackTrace !

VG Klaus
 

Avo_MODE

Mitglied
Ich habe das Problem nun behoben, indem ich mit den Threads und Timern herumgespielt habe.

Trotzdem danke für jegliche Hilfe.

#closerequest - falls es das gibt :D

LG Avo
 

Avo_MODE

Mitglied
Moin,
prima ;)


Und warum postet Du dann hier die Lösung nicht für die Nachwelt ?? :rolleyes:
VG Klaus
Wie gesagt, habe ich mit den Threads und Timern herumgespielt. Deshalb kann ich nicht genau beschreiben, wie ich den Fehler behoben habe. Allerdings ist mir aufgefallen dass der Timer nur einmal aufgerufen worden ist und deshalb keine Nachrichten abgerufen hat. Vielleicht hilft das der Nachwelt c:
 

JuKu

Top Contributor
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
Messoras Socket Chatserver mit mehreren OutputStreams Netzwerkprogrammierung 2
I ChatServer Netzwerkprogrammierung 9
J Socket Chatserver aus dem Internet nicht erreichbar Netzwerkprogrammierung 19
J Implementation Chatserver Netzwerkprogrammierung 4
L Probleme bei Chatserver Netzwerkprogrammierung 6
A ChatServer Grafisch aufbauen Netzwerkprogrammierung 4
T Kleiner Chatserver: Threads oder Multiplex? Netzwerkprogrammierung 18
I Performanteste Kommunikationsmethode zwischen Client u. Server Netzwerkprogrammierung 4
L Socket Automatische Zuweisung von Server und Client Rolle Netzwerkprogrammierung 12
ExceptionOfExpectation Server/Client-Kommunikation Netzwerkprogrammierung 34
M Server-Client-System für Browsergame Netzwerkprogrammierung 5
B Axis2 Webservice mit Client Zertifikat Authentifizierung Netzwerkprogrammierung 3
Yonnig Threads mit Client/Server und GUI (laufend bis button-click) Netzwerkprogrammierung 9
T Jetty mit Client-Zertifikat nur bei spezifischer URL Netzwerkprogrammierung 1
J Einlesen von Servernachrichten von TCP-Client Netzwerkprogrammierung 17
J Client-Server und SOAP Netzwerkprogrammierung 23
L30nS RMI Aufruf einer Client-Methode von einem RMI-Server Netzwerkprogrammierung 3
T String von Client zu Server kommt nicht an Netzwerkprogrammierung 92
D WebSocket Server mit HTML Client und Java Server Netzwerkprogrammierung 5
D Server - Client Informationsaustausch, Möglichkeiten Netzwerkprogrammierung 3
H Socket Chat entwickeln mit Java Server Client Netzwerkprogrammierung 4
X Kann ich einen Client/Server verbindung hinkriegen die mir alle paar Sekunden die aktuellen Daten per Realtime zuschickt ? Netzwerkprogrammierung 9
T Client zu Client Kommunikation Netzwerkprogrammierung 2
D Slf4j - Logging - Client-Server Architektur Netzwerkprogrammierung 3
J client server mit nur einem PC Netzwerkprogrammierung 33
M Socket Nachricht von TCP-Client an Server schicken Netzwerkprogrammierung 12
M Socket Verbindung Matlab(Server) Java(Client) Netzwerkprogrammierung 1
R Socket FATAL EXCEPTION MAIN bei Socket based client/server app Netzwerkprogrammierung 2
G Server-Client IO Problem Netzwerkprogrammierung 6
ruutaiokwu ständig "sender address rejected: improper use of smtp" bei smtp-client Netzwerkprogrammierung 4
J HTTP [Java 9] Neuer HTTP Client - Tutorial Netzwerkprogrammierung 3
I Socket Das erste Server-Client Programm Netzwerkprogrammierung 16
L Zugriffprobleme Client - Webservice AspenTechnology Netzwerkprogrammierung 0
A Client Client Übertragung Netzwerkprogrammierung 12
M Socket Server antwortet dem Client nicht Netzwerkprogrammierung 6
K Socket Netty Client wirft Fehler! Netzwerkprogrammierung 3
I Client/Server Kommunikation bei einem Spiel Netzwerkprogrammierung 4
E Objekte versenden, Client-Server Netzwerkprogrammierung 25
C Mini Client-Server-Anwendung funktioniert nicht Netzwerkprogrammierung 8
U Client Soap Verbindung wieder schließen Netzwerkprogrammierung 0
U Socket Client mit hash authentifizieren Netzwerkprogrammierung 3
F HTTP HTTP Rest Client mit TLS1.2 und selbst signiertem Zertifikat Netzwerkprogrammierung 2
P Server als Client nutzen Netzwerkprogrammierung 8
D Socket Run Args Client/Server Socket Netzwerkprogrammierung 1
Cromewell Socket Multithreaded Server und Client Netzwerkprogrammierung 1
Y Client/Server/DB communication Netzwerkprogrammierung 3
JavaWolf165 Socket mit .writeUtf etwas vom Client zum Server schicken Netzwerkprogrammierung 13
J Client - Serversocket Netzwerkprogrammierung 1
P RMI Client Server Programm über Internet Netzwerkprogrammierung 2
brainless Client Server Kommunikation verschlüsseln Netzwerkprogrammierung 13
gamebreiti Socket Server / Client Anwendung Manipulation von Objekten durch Server Netzwerkprogrammierung 9
T Socket Server/Client Kommunikation Netzwerkprogrammierung 8
N Fragen zu Sockets Client Netzwerkprogrammierung 3
F Extasys TCp Client extends Funktion Netzwerkprogrammierung 0
F Server Client Anwendung mit UDP Netzwerkprogrammierung 2
O Client zwischen XML und JSON auswählen lassen Netzwerkprogrammierung 2
A RMI Wo treten Exceptions bei RMI Aufrufen auf? Auf Client oder auf Server? Netzwerkprogrammierung 3
A ByteBuffer - Client/Server Netzwerkprogrammierung 9
A Socket Wie ein einfacher Multithreads Service mit Telnet als Client mit Observable/Observer gelöst.... Netzwerkprogrammierung 0
K C# Server - Android Client Netzwerkprogrammierung 0
T Application Client NullPointerExc Netzwerkprogrammierung 7
V TCP Client funktioniert auf Emulator aber nicht auf Smartphone Netzwerkprogrammierung 5
H Machbarkeitsfrage: TCP/IP Client (z.B. Netty) für Java Web Applcation Netzwerkprogrammierung 1
P MIME-TYPE Erklaerung, Kommunikation zwischen Client und Server Netzwerkprogrammierung 3
H HTTP REST Jersey - PUT-Beispiel von Client senden Netzwerkprogrammierung 0
J Sichere Kommunikation bei Server Client Netzwerkprogrammierung 3
T Frage zu Client-Server Applikation Netzwerkprogrammierung 2
H Socket Client/Server Socket Programmieren Netzwerkprogrammierung 1
M Theoretische Frage zu Server - Client Netzwerkprogrammierung 2
P HTTP Server / Client Netzwerkprogrammierung 1
N FTP FTP Client invalid IPv6 address (Apache Commons Net API) Netzwerkprogrammierung 6
F TCP Client, verbindung aufrecht halten Netzwerkprogrammierung 0
X RMI: Woher kennt der Client das Schnittstellen-Interface? Netzwerkprogrammierung 2
E Thematik Client server Netzwerkprogrammierung 2
D UDP Client empfängt nichts Netzwerkprogrammierung 2
D Client/Server per Crossover Lan Kabel Netzwerkprogrammierung 1
S Client Server Connection Netzwerkprogrammierung 4
V erste Client - Server Anwendung, paar Fragen wie Socketverbindung checken usw. Netzwerkprogrammierung 4
S Client Anwendung mit zentraler SQL-Datenbank Netzwerkprogrammierung 3
N Client Identifikation eines Servers Netzwerkprogrammierung 1
S Sichere Server/Client Architektur Netzwerkprogrammierung 1
D Chat Server/mehre Client Netzwerkprogrammierung 9
I Server+Client Netzwerkprogrammierung 3
N Client am Server abmelden Netzwerkprogrammierung 0
F Server/Client Probleme Netzwerkprogrammierung 3
D SSH Client Netzwerkprogrammierung 7
U Socket Instant Messanger (Server Linux, Client Windows) Netzwerkprogrammierung 1
B TCP Client Android Netzwerkprogrammierung 3
Athena Grundsatzfragen zu Client-Server-Architektur / Matchmaking Netzwerkprogrammierung 1
A Problem beim Senden von Client zu Server Netzwerkprogrammierung 10
F Client Server DB Netzwerkprogrammierung 0
A Verständnisfrage Multi-Threaded Client/Server Netzwerkprogrammierung 5
F Tipps zum Thema Server/Client vie SOAP Netzwerkprogrammierung 0
OnDemand Ist Client noch angemeldet? Netzwerkprogrammierung 7
F Socket Java - Server/Client simple Netzwerkprogrammierung 1
D Socket UDP Client reagiert nicht auf spontane Meldungen Netzwerkprogrammierung 5
R Zeitliche Syncronisation Server - Client Netzwerkprogrammierung 0
S Server-Client: Image senden Netzwerkprogrammierung 2
C Multithreading Client / Server erklärt Netzwerkprogrammierung 11
M Client sendet nur, wenn das Socket geschlossen wird Netzwerkprogrammierung 53

Ähnliche Java Themen

Neue Themen


Oben