# Server-Socket liest Input-Stream nicht



## Lui.k (4. Mai 2021)

Ich versuche einen super einfachen Server zu programmieren, welcher mit Webbrowsern wie zum Beispiel Firefox sprechen kann.

Wenn ich den Server über seine interne IP (192.168.2.XXX) anspreche, funktioniert alles wie erwartet.

Wenn ich dasselbe von extern versuche, funktioniert es nicht mehr so ganz.

Ich verwende einen ServerSocket, warte auf eine Anfrage und erstelle anschließend einen InputStream und einen OutputStream.

[CODE lang="java" title="ServerSocket" highlight="15"]        ServerSocket serverSocket = new ServerSocket(Port);

        System.out.println("");
        Socket clientSocket = serverSocket.accept();
        System.out.println("accept");

        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        StringBuffer daten  = new StringBuffer();
        String tmp = "";

        while(true) {  

            tmp = in.readLine();

            if(tmp == null || tmp.length() == 0) {
                break;
            } else {
                daten.append(tmp);
            }
        }
        System.out.println(daten.toString());
[/CODE]

Das Problem ist in Zeile 15. Der Code wird ab hier nicht weiter ausgeführt. Es ist auch nicht so, dass die Schleife nicht verlassen wird. Ich habe auch schon versucht anstelle von "*n.readLine()*" - "*in.read()*" zu verwenden. Ich habe auch schon versucht "*InputStream in = clientSocket.getInputStream()*" anstelle von "*BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))*" zu verwenden ... ohne Erfolg.

Wenn ich im Browser die Verbindung unterbreche, kommt die Anfrage des Browsers beim Server an. Aber dann kommt die Rückantwort des Servers nicht mehr beim Browser an. Wenn ich die while-Schleife weglasse, funktioniert es. Mache ich hier etwas grundsätzliches Falsch? Ich muss doch die Anfrage des Clienten lesen, bevor ich ihm antworte.

Ich verwende Ubuntu 20.04.2 LTS und JavaSE-1.8. Vielen Dank im Voraus!!!


----------



## kneitzel (4. Mai 2021)

Das kann doch so gar nicht funktionieren! readLine ist ein blockierender Call bis eben eine Zeile gelesen wurde oder die Verbindung geschlossen wurde.
Und du wiederholst dies immer, d.h. die Schleife blockiert, bis die Verbindung geschlossen wurde.

Du musst Dir erst einmal genau überlegen, was da das Protokoll sein soll. Woran kann der Server erkennen, dass der Client seine Sendung beendet hat? Oder ist es Zeilenorientiert? Dann könntest Du mit mehreren Threads arbeiten und der Empfangen-Thread würde halt regelmäßig blockieren ... (Oder Du machst das alles asynchron. Gerde bei Server Applikationen macht dies Sinn.)


----------



## Lui.k (4. Mai 2021)

@kneitzel 

Danke sehr für deine Antwort!

Ja du hast recht. Es ist scheinbar so, das die Methode *in.readLine();* den Code blockiert bis die Verbindung geschlossen wird.

Komisch ist, dass dieser Code funktioniert, wenn ich den Server über die Lokale IP (192.168.2.XXX) anspreche.

Solange die Verbindung aktiv ist, wird die Schleife nicht mehrfach ausgeführt. Das passiert erst, wenn ich die Verbindung trenne, dann werden mehre Zeilen gelesen.

Die letzte Zeile der Anfrage ist leer (also 0 Zeichen), daran erkenne ich das die Anfrage zu Ende ist. Aber so weit komme ich nicht, da mir *in.readLine();* nichts zurück liefert so lange die Verbindung besteht.

Entschuldige bitte, dass ich so dumm nachfragen muss, aber was würde es nutzen einen neuen Thread zu beginnen. Ich möchte doch zuerst die anfrage des Clienten lesen, bevor ich etwas anderes tue, oder?

Danke sehr für deine Hilfe!!!


----------



## kneitzel (4. Mai 2021)

Bezüglich Deiner Aussagen kann ich Dir nicht folgen:
- Das Verhalten sollte immer gleich sein, egal b der Socket über die lokale ip angesprochen wird oder nicht.
- Der Client sollte die Daten eigentlich direkt senden. Ein Webbrowser macht ein fluch, denn die Daten müssen ja zum Server gehen. Der Client wartet dann ja auch auf eine Antwort.

Zum Starten von Threads gäbe es z.B. https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

Aber evtl. wäre es besser, wenn man direkt async arbeiten würde. Da wäre z.B.








						A Guide to NIO2 Asynchronous Socket Channel | Baeldung
					

A quick and practical guide to Java NIO2 Asynchronous Socket Channel API




					www.baeldung.com
				




Generell kannst Du aber auch einfach schauen, wie das Andere so gemacht haben. Es gibt viele Veröffentlichungen dazu. Ich habe mal einfach nach java simple chat application gesucht und eines der ersten Treffer war dann:








						Creating a Chat Server Using Java
					

Creating a Chat Server Using Java: Introduction Networking is a major branch of programming that is vital to connecting users through devices. As such many programming languages have multiple ways to form connections users and servers or between peers. For starting out programming, J…




					www.instructables.com
				




Ich habe mir das nicht im Detail angesehen, aber ich denke, dass dies schon helfen kann.

Wenn Du als client ein Webbrowser nutzen willst, dann wäre aber auch ggf. die Frage, wieso Du keinen Bestehenden Server für sowas nutzt (Sprich: bestehende Web Technology nutzen wie z.B. spring boot, JEE/Jakarta, ....)


----------



## Lui.k (4. Mai 2021)

kneitzel hat gesagt.:


> Bezüglich Deiner Aussagen kann ich Dir nicht folgen:
> - Das Verhalten sollte immer gleich sein, egal b der Socket über die lokale ip angesprochen wird oder nicht.
> - Der Client sollte die Daten eigentlich direkt senden. Ein Webbrowser macht ein fluch, denn die Daten müssen ja zum Server gehen. Der Client wartet dann ja auch auf eine Antwort.
> 
> ...


Ich stimme Dir 100% zu. Es sollte keinen Unterschied machen ob der Socket über die lokale IP angesprochen wird oder nicht ... aber trotzdem ist es so.

Danke sehr für die Links und Deine Hilfe!

Ich schreibe, sobald / falls ich eine Lösung finde.


----------



## Gelöschtes Mitglied 65838 (4. Mai 2021)

[CODE lang="java" title="Client"]package application;
public class Client
{
    public static void main(String[] args) throws Exception
    {
        Socket socket = new Socket("127.0.0.1", 4000);
        BufferedWriter writerChannel = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader readerChannel = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;

        writerChannel.write(new Date().toString() + "\n\r");
        writerChannel.flush();

        while ((line = readerChannel.readLine()) != null)
        {
            System.out.println(line);
        }
    }
}[/CODE]
[CODE lang="java" title="Server"]package application;
            while (true)
            {
                Socket socket = listener.accept();
                BufferedReader readerChannel = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter writerChannel = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

                    writerChannel.write(new Date().toString() + "\n\r");
                    writerChannel.flush();

                    while ((line = readerChannel.readLine()) != null)
                    {
                        System.out.println(line);
                    }

}[/CODE]
das ist ein ganz ganz simpler server und client ausschnitt wo man bei der verbindung beim client und beim server sieht wann sich jemand verbunden hat um die "verklemmung" zu umgehen


----------

