Anfängerfrage: Socketverbindung zu einem Server?

Hallo,

ich bin totaler Newbie in Java und insbesondere auch beim Thema Netzwerk. Wir behandeln das Thema gerade in der Schule. Jetzt sollen wir einen “einfachen” Client programmieren, der sich bei einem Server anmeldet und daraufhin in unregelmäßigen Abständen Nachrichten übermittelt bekommt. Die Nachrichten sind unterschiedlich lang, als ANSI 1252 kodiert und werden mit 0x00 terminiert.

Der Client soll permanent die Verbindung halten. Sprich bei Verbindungsabbrüchen die Verbindung wieder herstellen. Um eine Verbindung herzustellen muss dieser HalloServer0x00 an den Server schicken. Danach schickt der Server mal mehr mal weniger Daten, die einfach auf der Konsole ausgegeben werden sollen.

Das ist derzeit mein Client:

 void connect() throws IOException {
    String ip = "192.168.1.1";
    int port = 7009;
    java.net.Socket socket = new java.net.Socket(ip,port); // verbindet sich mit Server
    String zuSendendeNachricht = "Hello World".(byte)0;
    PrintWriter printWriter =new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
    printWriter.print(zuSendendeNachricht);
    printWriter.flush();

    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    char[] buffer = new char[200];
    while (true)
        int anzahlZeichen = bufferedReader.read(buffer, 0, 200);
        String nachricht = new String(buffer, 0, anzahlZeichen);
        System.out.println(nachricht);
   }
}

Wenn ich es richtig verstehe muss ich die Nachricht als Byte abschicken. Wie konvertiere ich meine Nachricht in Bytes und sende diese dann ab? Und wie kann ich beim Empfangen prüfen ob ich eine Nachricht vollständig gelesen habe also bis 0x00 und woran erkenne ich wann die nächste kommt? Ich habe das lesen jetzt einfach in einer Schleife mit true, wie kann ich denn prüfen ob die Verbindung besteht? Gibt es sowas wie SocketConnectionOk?

Ihr merkt an den Fragen sicherlich das ich keinen Plan habe! Hoffe auf etwas Hilfe!

Vielen Dank und schönen abend!

ist der Server auch von dir programmiert oder im Quellcode einsehbar oder gibt es mehr an Anleitung, lauffähige Beispielprogramme?
kannst du es ausprobieren, gibt der Server Rückmeldung?

von Beschreibungen a la ‘werden mit 0x00 terminiert’ halte ich nicht viel,
das kann ein String mit diesen 4 Zeichen sein, oder 2x Byte 0 oder wer weiß was sonst je nach Kodierung

das ist keine Programmierung sondern simples Ausprobieren, nicht viel anspruchsvoller als der neue ausgepackte Mixer von Weihnachten :wink:

empfangene Nachrichten kannst du dir anschauen, im byte[],
frickelig könnte es werden falls mal mehr als 200 auf einmal ankommen,
falls das erste Lesen nur einen Teil enthält,
der Einfachheit halber wollen wir das hoffentlich erstmal ausschließen, achte aber trotzdem darauf,

wie viele Bytes gelesen, wie sehen die letzten aus, immer 2x 0?
das könnte dir einen Hinweis geben was selber zu senden, nur leider musst das wohl schon vorher erfolgreich machen…,
bei der String-Erstellung jedenfalls evtl. diese bytes weglassen

Verbindungabbruch merkt man wohl am besten an einer Exception bei Lesen & Co.,
mache ein try/catch und eine Schleife um den connect()-Aufruf, wiederhole das connect() wenn nötig

programmiere evtl. testweise einen eigenen Server, simuliere dort einen Abbruch durch close(),
Programmende (dann wird allerdings reconnect schwer), was auch immer,
Beispiele gibts überall, ip=“localhost”


das Forum leidet aktuell unter Spam, anonyme Beiträge werden nur beizeiten freigeschaltet,
mit einer Anmeldung könntest du dir selber helfen :wink:

Der Server ist eine Black-Box, Beispiele gibt es keine. das 0x00 soll wohl ein Byte 0 sein. Und jede Nachricht die der Server sendet wird mit einem Byte 0 getrennt. Also etwa so:

Nachricht1(Byte0)Nachricht2(Byte0)PAUSENachricht3(Byte0)

Wie kann ich denn die Nachricht Zeichen für Zeichen einlesen und nach dem Byte0 prüfen?

du liest sie ja in ein Array ein, vielleicht ist ein char 0,
wobei das wirklich erst ein Thema wird wenn Senden geht und überhaupt etwas empfangen wird, schon soweit?

Was mir auffällt ist Zeile 6 deines Codes : String zuSendendeNachricht = "Hello World".(byte)0;
Du/Ihr habt vermutlich vorher mit PHP gearbeitet, oder ? Denn so spontan würde mir erstmal nur PHP einfallen wo String-concats mit “.” durchgeführt werden. In Java würde das so aber nicht funktionieren, denn in Java hat “.” eine andere Bedeutung als in PHP.
Willst du in Java zwei String mit einander verbinden nutzt du dazu “+”, also würde sich deine Zeile so ändern : String zuSendendeNachricht = "Hello World"+(byte)0;
Auch deutet dein “(byte)0” darauf hin das du allgemein noch nicht viel mit Java gearbeitet hast. Auch wenn es korrekt ist, so hat es sich in Java eingebürgert das man Byte-Werte in hexadezimaler Schreibweise angibt : 0x00, wobei es egal ist ob man bei Werten kleiner als 0x10 (dez: 16) immer 0x0X schreibt oder direkt 0xX, da hat jeder so seinen eigenen Stil. Auch ist ein Cast auf byte zumindest an dieser Stelle nicht nötig. In Java sind alle Literale grundsätzlich erstmal int, erst durch casten oder konkrete Deklaration weist man ihnen den gewünschten Wertebereich zu. Ist auch eigentlich hauptsächlich nur für negative Werte interessant da es dann dabei drauf ankommt wo das sign-Bit steht und wie es interpretiert werden soll.

Folglich würde man ungefähr sowas schreiben : String zuSendendeNachricht = "Hello World"+0x00;

Nun ist es aber allgemein eher ungünstig Strings mit “+” aneinander zuhängen, vorallem wenn es dabei um Literale geht. Zwar erkennt der Compiler das und baut da was entsprechend sauberes draus, aber man sollte es dann doch schon gleich richtig schreiben. Dafür gibt es Escape-Sequenzen : “\xx”. Der Backslash “” leitet eine Escape-Sequenz ein, danach folgenden dann entweder direkt numerische Literale, bestimmte Konstante wie "
" oder es werden durch bestimmte Kombinationen gewisse Interpretierungen erzwungen : \uxxxx > Unicode-Zeichen.
Ein (byte)0x00 kann man auch verkürzt so darstellen : “\0”.

Das drückt dann dein Literal noch weiter zusammen in die “finale” Form : String zuSendendeNachricht = "Hello World\0"; -> ein \0-terminierter C-String.

Daraus kann man ableiten das der Server entweder in C bzw einer C-verwandten Sprache geschrieben ist oder C-Strings simuliert werden sollen.
Wie Slater schon erwähnte : in Java eher unüblich und kann auch mal sehr schnell zu Fehlern führen.

Dann kam noch die Frage wie man denn den Delimiter \0 prüfen kann. Nun, ich bin mir erlich gesagt nicht sicher ob für diese Aufgabe BufferedReader/Writer wirklich so sinnvoll sind. Ich denke der Aufgabensteller hatte hier direktes Arbeiten mit Input/OutputStream und read()/write() in Gedanken.
Dann wäre es recht einfach : solange read() bis man ein 0x00 erhält was das Ende der aktuellen Nachricht kennzeichnet. Mit einem BufferedReader und read(byte[]) (mal von abgesehen das read(byte[]) im Kontext eines Readers eigentlich keinen Sinn macht) gehts auch, aber man hat eigentlich mehr Schreibaufwand.

Zum Re-Connect bei Verbindungsabbruch : da kam die Lösung schon von Slater : um das ganze Konstrukt ein try-catch mit einem Loop und einem Flag. Da gibts im Netz auch ein paar simple Beispiele.

@TO
Bitte vermeide Cross-Threads, oder weise, wenn du es schon tust, dann auch bitte drauf hin : [noparse]http://domain.tld/netzwerkeprogrammierung/164935-tcp-verbindung-byte-weise-lesen.html[/noparse]