# Warum sind Sockets für einen Live-Chat sinnvoll?



## jemand (14. Okt 2017)

Hi Java-Devs,

ich bin gerade dabei, einen Live-Chat zu schreiben und hab mich im unteren Thread mal darüber schlau gemacht.
Aber wieso sollte ich unbedingt auf Sockets zurückgreifen? Der Socket-Server würde ja auch über eine Endlosschleife auf neue Chat-Nachrichten warten und diese an den Client weitergeben, sodass es ja keine Geschwindigkeitsvorteile gibt und ich meinen Chat auch ohne Sockets schreiben kann.

Kann mich mal jemand darüber aufklären?

Danke


----------



## Tobse (15. Okt 2017)

Wie willst du denn den Chat ohne Sockets schreiben?

HTTP Polling:
Ist vieeeel langsamer und verschwendet Ressourcen. Außerdem geht HTTP auch nur über Sockets.

HTTP Long Polling:
Ist vllt gleich schnell wie rohe Sockets, verschwendet aber auch Ressourcen und ist unnötiger Mehraufwand.

Websockets:
Ist das selbe wie ein Socket, nur mit mehr Overhead.


----------



## jemand (15. Okt 2017)

Ja klar muss ich auf irgendein Socket zurückgreifen. Ich meinte natürlich, ohne einen eigenen entwickeln zu müssen. Aber wenns über http natürlich langsamer geht, kann ich auch einen eigenen entwickeln. Ist angekommen. Wenn ich mir einen server miete, kann ich ja dort dann den Dienst automatisch starten lassen und gebe meinen eigenen Port frei.


----------



## Tobse (15. Okt 2017)

jemand hat gesagt.:


> Ja klar muss ich auf irgendein Socket zurückgreifen. Ich meinte natürlich, ohne einen eigenen entwickeln zu müssen. Aber wenns über http natürlich langsamer geht, kann ich auch einen eigenen entwickeln. Ist angekommen.


Ein eigenes Protokoll für soetwas zu entwerfen ist nicht so schwierig, wie du jetzt vielleicht denkst. Und in jedem Fall ist es eine Lehrreiche Erfahrung  Ich würde sagen: go, mach rohe Sockets mit deinem eigenen Protokoll. Ein bisschen Frust und viele Erfolgserlebnisse später steht dein Chat und du bist klüger als davor 



jemand hat gesagt.:


> Wenn ich mir einen server miete, kann ich ja dort dann den Dienst automatisch starten lassen und gebe meinen eigenen Port frei.



Richtig.

----
Wenn du auf ein bestehendes Protokoll zurückgreifen willst kann ich dir XMPP empfehlen; wenn du das Protokoll nutzt kann deine Software auch mit vielen anderen Servern und Clients kommunizieren.


----------



## JuKu (18. Okt 2017)

Sockets sind der Grundbaustein für Networking allgemein. Auch eine HTTP Verbindung basiert auf Sockets. Ohne Socket gibt es kein Networking (korrigiert mich, wenn ich falsch liege! Bei UDP bin ich mir gerade unsicher).
Du könntest entweder eine der Methode von @Tobse verwenden, oder einfach alle x Millisekunden eine HTTP Anfrage an den Server stellen. Letzteres kostet aber viel mehr Performance, da TCP einen sog. "Slow Start" besitzt:
https://de.wikipedia.org/wiki/Transmission_Control_Protocol#Slow_Start_und_Congestion_Avoidance
https://de.wikipedia.org/wiki/Transmission_Control_Protocol#Slow_Start_und_Congestion_Avoidance
D.h. konkret, dass es vergleichsweise lange dauert, eh eine Verbindung aufgebaut wird. Und deshalb willst du für einen Chat nicht ständig Verbindungen neu öffnen und direkt wieder schließen, sondern hälst sie lieber offen ("normaler" Socket).


----------



## jemand (18. Okt 2017)

So, roher Socket steht und es wird jede Sekunde aktualisiert. Aber ich will eben nicht jede Sekunde eine neue Connection öffnen. Deswegen hab ich eine Abfrage reingemacht, ob die Verbindung offen ist oder nicht. Jetzt lässt sich aber socket.getInputStream() nicht resetten. Gibt es dafür eine Möglichkeit?


----------



## JuKu (18. Okt 2017)

jemand hat gesagt.:


> Aber ich will eben nicht jede Sekunde eine neue Connection öffnen.



Genau deshalb nutzt du ja gerade Sockets.



jemand hat gesagt.:


> Deswegen hab ich eine Abfrage reingemacht, ob die Verbindung offen ist oder nicht. Jetzt lässt sich aber socket.getInputStream() nicht resetten. Gibt es dafür eine Möglichkeit?



Wenn dein Client startet, dann verbindet er sich zum Server.
Wieso willst du socket.getInputStream() denn resetten? Welchen Sinn soll das haben?

Ich glaube es ist für dich einfacher, wenn du erst einmal eine Library wie Vertx verwendest. Anscheinend hast du noch nie mit Networking in Java gearbeitet, da ist etwas Abstraktion vllt. um einiges einfacher.
Dazu verweise ich immer wieder gerne auf meine beiden Tutorials, wie man einen Chat Server & Client mit Vertx schreibt (vollständiger Code liegt auch bei):

[Tutorial] Ein Chat Server in Java – Teil 1 / 2
[Tutorial] Ein Chat Server in Java – Teil 2 / 2


----------



## jemand (19. Okt 2017)

Danke für die Antworten. Ich kann ja mal den Code schicken, so wie ich mir das vorgestellt habe. Ich habe auch nicht vor, ein professionelles Chat-System zu schreiben, sondern es dient nur als Nebenprodukt für meine App. Nun ist es aber so, dass ich die Server-Seite per PHP realisiere. Trotzdem kann ich ja mal den Code schicken und vielleicht habt ihr paar Tipps, wie ich es schaffen kann, dass ich die Connection nur einmal öffnen brauche. So wie ich es gemacht habe, wird zwar die Connection nur einmal geöffnet, aber beim zweiten Mal ist dann der InputStream vom Socket leer.

Client:


```
public class SocketTask extends AsyncTask<String, Void, String> {

    private int port;
    private List<String> paramList = new ArrayList<String>();

    public SocketTask(int port, List<String> paramList) {
        this.port = port;
        this.paramList = paramList;
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            if (SocketProvider.socket == null) {
                SocketProvider.socket = openConnection(port);
            }
            sendToServer(SocketProvider.socket);
            return readFromServer(SocketProvider.socket);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private Socket openConnection(int port) throws Exception {
        SocketAddress socketAddress = new InetSocketAddress(ServerData.HOST_NAME, port);
        Socket socket = new Socket();
        socket.connect(socketAddress, 10000);
        return socket;
    }

    private void sendToServer(Socket socket) throws IOException {
        OutputStream outputStream = socket.getOutputStream();
        PrintStream printStream = new PrintStream(outputStream);

        for (String string : paramList) {
            printStream.println(string);
        }
    }

    private String readFromServer(Socket socket) throws IOException {
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

        StringBuilder stringBuilder = new StringBuilder();

        String line = null;
        while ((line = bufferedReader.readLine()) != null) {
            stringBuilder.append(line);
        }

        return stringBuilder.toString();
    }

}
```


```
<?php

    require_once "Connection.php";
    $connection = connect();

    set_time_limit (0);
    ob_implicit_flush ();

    $address = '192.168.43.59';
    $port = 10000;

    if (($sock = socket_create(AF_INET, SOCK_STREAM, 0)) === false) {
        echo socket_strerror(socket_last_error())."\n"; 
    }
   
    if (socket_bind($sock, $address, $port) === false) {
        echo socket_strerror(socket_last_error())."\n";
    }
   
    if (socket_listen($sock, 1000) === false) {
        echo socket_strerror(socket_last_error())."\n";
    }

    while (true) {
        if (($client = socket_accept($sock)) === false) {
            echo socket_strerror(socket_last_error())."\n";
            break;
        }
           
        $buffer = socket_read($client, 2048, PHP_NORMAL_READ);
       
        echo "input:".$buffer;
       
        $jsonOfBuffer = json_decode($buffer, true);
        $loggedUser = $jsonOfBuffer["loggedUser"];
        $partner = $jsonOfBuffer["partner"];
       
        require_once "getMessages.php"; // beinhaltet SELECT-Command für Messages
       
        $result = getMessages($connection, $loggedUser, $partner);
        socket_write($client, $result, strlen($result));
       
        echo "output:".$result;
       
        socket_close($client);
    }
   
    socket_close ($sock);
   
    close($connection);
?>
```


----------



## JuKu (23. Okt 2017)

@jemand Ich habe selbst lange Zeit PHP programmiert und bin für mich persönlich zu dem Fazit gekommen, dass Sockets in PHP eher nicht so die geilste Lösung sind.
PHP ist eher für "normale" HTTP Anwendungen gedacht gewesen, also für Anwendungen die eine Verbindung zum Server aufbauen, Daten hinschicken, PHP eine Antwort generiert und die Verbindung dann schließt.
Vermutlich erzeugen da Sockets eher Overhead, aber das müsste man wohl mal richtig evaluieren.

Willst du wirklich PHP verwenden? Was spricht gegen ein Java Backend? Dass ein Webspace nicht reicht?
Bitte bedenke: Wenn du einen normalen Webspace hast, dann werden solche Chat Systeme in den AGBs meist nicht geduldet und Sockets werden bei Webspace normalerweise auch gar nicht zugelassen. Einen richtigen (Root / vServer) Server brauchst du also sowieso.


----------

