Zusi 3 TCP-Protokoll-Implementation für .Net

Alles, was nicht in die anderen Kategorien passt.
Nachricht
Autor
Andreas Karg
Beiträge: 4718
Registriert: 28.04.2002 12:56:00
Kontaktdaten:

Zusi 3 TCP-Protokoll-Implementation für .Net

#1 Beitrag von Andreas Karg »

Servus mitnand,

F. Schn. und ich sind an der Implementierung des Z3-Protokolls für .Net dran. F. hat ja bereits hier einen Adapter bereitgestellt, der zumindest einfache Aufgaben erfüllen sollte.

Die neue Version wird eine komplette Neuentwicklung, diesmal im Gegensatz zur historisch gewachsenen Z2-Schnittstelle ordentlich Test Driven ge-Developt und glänzend und schön.
Die Schnittstelle zur Nutzeranwendung soll dabei idealerweise idiotensicher werden, sodass man auch als Neuling schnell eine Applikation zusammengeschraubt bekommt.

Stand 12.03.16:
Im bekannten Github-Repo könnt ihr sie euch angucken - momentan im Arbeitsbranch feature/rewrite und etwas unelegant in die bisherige Ordnerstruktur eingebaut: Die Neuimplementierung ist im Ordner "ZusiTcpInterface", mit den entsprechenden Tests im Ordner "ZusiTcpInterfaceTests". Alle zusammen, alt, neu und Tests sind in der gemeinsamen Visual Studio Solution drin.

Der aktuelle Stand besteht nur aus etwas Infrastruktur und ist in der Lage, sich beim Fahrsimulator mit Hello anzumelden und dessen Antwort auf "wurde akzeptiert" zu überprüfen.

Als nächstes will ich behelfsmäßig eine Messgröße anfordern und dann schauen, wie ich die zurückkommenden Daten kontinuierlich und zuverlässig in eine Client-Anwendung weiterschaufeln kann.
Aktuell sieht mein Plan einen Hintergrund-Thread vor, der die Netzwerkkommunikation selbst übernimmt und empfangene Pakete in sinnvolle Datenstrukturen umwandelt. (z.B. "Neuer Wert für [Geschwindigkeit] = 123.4 km/h") Die wiederum landen in einer thread-sicheren Queue, die die einzige Schnittstelle zwischen dem Hintergrund- und dem Anwenderthread darstellt. Auf Empfängerseite wiederum sind diverse Lösungen denkbar: Von "Anwendung liest Queue periodisch selber" bis hin zu "Automatismus, der wie in der alten Version automatisch Events in die Windows Message Loop wirft".

Damit sollte sich eine schöne, elegante Schnittstelle für Anfänger wie Hacker zusammenschrauben lassen.

Feedback freilich jederzeit willkommen :)
Zuletzt geändert von Andreas Karg am 12.03.2016 22:21:55, insgesamt 1-mal geändert.

Benutzeravatar
Roland Ziegler
Beiträge: 5508
Registriert: 04.11.2001 22:09:26
Wohnort: 32U 0294406 5629020
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#2 Beitrag von Roland Ziegler »

Andreas Karg hat geschrieben:Feedback freilich jederzeit willkommen :)

Code: Alles auswählen

System.Int64 currentLength2 = Buffer[Offset] + 0x100 * Buffer[Offset + 1] + 
0x10000 * Buffer[Offset + 2] + ((System.Int64) 0x1000000) * Buffer[Offset + 3];
Schaut Euch mal die Klasse System.BitConverter an. Vielleicht weniger Schreibarbeit.

Benutzeravatar
F. Schn.
Beiträge: 6630
Registriert: 24.10.2011 18:58:26

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#3 Beitrag von F. Schn. »

Das war der ursprüngliche Plan. Allerdings war ich damals nicht in der Lage, die Endianness einzustellen. Vielleicht habe ich aber auch gerade Tomaten auf den Augen...
Diese Signatur möchte folgendes bekannter machen: ZusiWiki · ZusiSK: Streckenprojekte · YouTube: Objektbau für Zusi · euirc: Zusi-Chat

Andreas Karg
Beiträge: 4718
Registriert: 28.04.2002 12:56:00
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#4 Beitrag von Andreas Karg »

Endianness kann man beim normalen BitConverter nicht auswählen, leider. Von Jon Skeet (allgemein vergötterter C#-Guru) gibt's aber einen Wrapper (oder Neuimplementierung - bin mir nicht sicher), bei dem man die Endianness explizit festlegen kann: http://pobox.com/~skeet/csharp/miscutil" target="_blank

Gibts auch auf NuGet und verwende ich in der Neuimplementierung schon recht großzügig.
Die Endianness beim BitConverter war mir schon immer ein Dorn im Auge...

Benutzeravatar
Max Senft
Administrator
Beiträge: 3004
Registriert: 04.11.2001 14:01:40
Aktuelle Projekte: Dies und das
Wohnort: Blieskastel, Saarland, Deutschland
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#5 Beitrag von Max Senft »

Hi,

also die Diskussion um die Endianess verstehe ich nicht. Es muss doch nur IsLittleEndian geprüft werden und entsprechend das jeweilige Byte-Array gedreht werden. Die Transport-Endianess ist doch immer BigEndian, oder?! Und nur je nach Ziel-Endianess muss gearbeitet werden.

Kopfkratzende Grüße
Max
Administrator, Programmierer, Ansprechpartner bei Problemen mit dem Board

Benutzeravatar
F. Schn.
Beiträge: 6630
Registriert: 24.10.2011 18:58:26

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#6 Beitrag von F. Schn. »

Max Senft hat geschrieben:Die Transport-Endianess ist doch immer BigEndian, oder?!
Das ist die Frage. Ich habe jedenfalls nicht innerhalb meiner Gedult eine Garantie dafür in den Doku gefunden. ;) Allerdings ist der Punkt einer, den ich für verhältnismäßig wichtig zu lösen halte.
Zuletzt geändert von F. Schn. am 12.03.2016 23:46:52, insgesamt 1-mal geändert.
Diese Signatur möchte folgendes bekannter machen: ZusiWiki · ZusiSK: Streckenprojekte · YouTube: Objektbau für Zusi · euirc: Zusi-Chat

Benutzeravatar
Johannes
Beiträge: 3197
Registriert: 14.03.2009 22:36:06
Aktuelle Projekte: Zusitools (http://git.io/zusitools)

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#7 Beitrag von Johannes »

Laut Doku 11.3.1.3: "Die Integer-Werte werden in Intel-byte-order versandt." Das gilt fuer Float-Werte meiner Erfahrung nach auch.

Benutzeravatar
Roland Ziegler
Beiträge: 5508
Registriert: 04.11.2001 22:09:26
Wohnort: 32U 0294406 5629020
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#8 Beitrag von Roland Ziegler »

Im Regelfall umfasst Endianness auch Floating Point.

Aber, wie schon angedeutet, die Konvertierung, sofern erforderlich, findet eine Stufe weiter unten statt, kein Stück Anwendungsfachklasse sollte sich damit beschäftigen.

Ich habe jetzt Eure Implementierung nicht so sehr genau erforscht, die Motivation, überhaupt mit Byte-Arrays zu arbeiten, hat sich mir daher noch nicht erschlossen. Warum lest Ihr nicht direkt vorm Stream? Das zugrunde liegende Modell ist doch auch in .Net ein mächtiges, und wenn ich mich recht erinnere, ist der .Net Socket Reader bereits als Stream ausgeprägt. Stream mit BinaryReader umhüllt, und schon ist man das Byte-Array als Zwischenstufe los.

Beim exotischen Zusi-TCP-Protokoll ohne Paketschicht mag es allerdings erforderlich werden, noch eine eigene Stream-Klasse zu implementieren, um das Wohlbefinden des Sockets zu diagnostizieren, was bei üblichen Industrieprotokollen der Paket-Layer anwendungsunabhängig erledigen würde. Aber auch das sollte für Knoten- oder Attributsfachklassen transparent bleiben.

Ich komme deswegen darauf, weil ich selbst BitConverter höchst selten anwende, sondern immer BinaryReader, auch eigene Implementierungen davon, z.B. wg. Endianness.
Zuletzt geändert von Roland Ziegler am 13.03.2016 11:24:50, insgesamt 1-mal geändert.

Benutzeravatar
Max Senft
Administrator
Beiträge: 3004
Registriert: 04.11.2001 14:01:40
Aktuelle Projekte: Dies und das
Wohnort: Blieskastel, Saarland, Deutschland
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#9 Beitrag von Max Senft »

Hi,

@Roland: so hatte ich meine Implementierung begonnen. Eine recht "Abstrakte" Implementierung eines "Stream-Handlers", der letztendlich Klassen serialisiert/deserialisiert, die über Attribute definiert werden.

Aber wie heißt es so schön: Mehrere Wege führen nach Rom. Und am Schluss zählt, dass es funktioniert. Ob es nun hübsch und elegant implementiert ist oder nicht. :) Hauptsache es ist wartbar und kann leicht erweitert werden, wenn denn da in der hoffentlich nicht so fernen Zukunft weitere tolle Möglichkeiten in Zusi daher kommen, über die man Zusi "manipulieren" kann.

Grüße
Max
Administrator, Programmierer, Ansprechpartner bei Problemen mit dem Board

Andreas Karg
Beiträge: 4718
Registriert: 28.04.2002 12:56:00
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#10 Beitrag von Andreas Karg »

@Roland
BinaryReader ist eine prima Idee - da hätte ich selber auch drauf kommen müssen. Wird geändert...

Benutzeravatar
F. Schn.
Beiträge: 6630
Registriert: 24.10.2011 18:58:26

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#11 Beitrag von F. Schn. »

BinaryReader habe ich auch in Betracht gezogen, die Endianness war da aber auch unauffindbar. Außerdem war mir nicht ganz geheuer, wie das Verhalten von noch nicht vollständig eingegangen Daten behandelt wird. 8o

Hätte das Zusi-3-Protokoll eine Längenangabe, wie groß ein einzelnes Paket insgesammt wäre, wäre das unter Zuhilfenahme des MemoryStream völlig Problemlos machbar. Was man aber durchaus machen könnte, wäre, die Funktionen in einer eigenen Klasse umzusetzen. Beim BinaryWriter hat man diese Probleme nicht, bleibt dort als Problem nur noch die Endianness.

Momentan arbeitet Andreas gerade an einer geänderten Implentierung der Nodes und Attributes, so dass ich die Umsetzung des verbesserten IO erst mal zurückstelle (ist für den Nutzer eh erst mal nur Backend). Aber um ehrlich zu sein, würde mich auch dein Ansatz, Max, mal interressieren. Hast du Lust, das Repository mal zu forken?
Diese Signatur möchte folgendes bekannter machen: ZusiWiki · ZusiSK: Streckenprojekte · YouTube: Objektbau für Zusi · euirc: Zusi-Chat

Benutzeravatar
Roland Ziegler
Beiträge: 5508
Registriert: 04.11.2001 22:09:26
Wohnort: 32U 0294406 5629020
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#12 Beitrag von Roland Ziegler »

F. Schn. hat geschrieben:BinaryReader habe ich auch in Betracht gezogen, die Endianness war da aber auch unauffindbar. Außerdem war mir nicht ganz geheuer, wie das Verhalten von noch nicht vollständig eingegangen Daten behandelt wird.
Der BinaryReader ist eine Adapter-Klasse. Er gibt die Leseanforderungen an den Stream weiter, siehe http://referencesource.microsoft.com/#m ... yreader.cs" target="_blank
Hätte das Zusi-3-Protokoll eine Längenangabe, wie groß ein einzelnes Paket insgesammt wäre, wäre das unter Zuhilfenahme des MemoryStream völlig Problemlos machbar.
Deswegen spreche ich von "exotisch". Übliche Protokolle haben diesen zusätzlichen Layer, mit Längenangabe und ggf. weiteren Metadaten. Dann kann man mit einem Framework ansetzen, das für eine Unzahl von Protokollen geeignet ist, ohne den Aufbau des tatsächlichen Protokolls kennen zu müssen, solange die Paketschicht aus einem Kopf fester Länge und anschließendem variablen Datenteil besteht - was normalerweise gegeben ist, aber hier halt nicht. So ein Framework erledigt dann beispielsweise wählbare Client- und Serverrolle, Verbindungsaufbau/-abbau, Fehlererkennung, Wiederverbinden beim Client, Mehrfachverbindungen beim Server, und auch Pinging/Stayalive.

Funktioniert nach dem Design Pattern "Dependency injection", mächtig und universell, und möglich allein über Interfaces. Der von Max vorgeschlagene C#-Attributansatz ist nicht nötig. Leider ist diese Framework-Idee hier so nicht anwendbar, also genug der Abschweifung.

Endianess kann man in einen eigenen BinaryReader packen, der von System.IO.BinaryReader ableitet. Die Methoden des Basisklassen sind nämlich virtuell. Das wird aber bei Zusi nicht gebraucht, siehe Hinweis auf Intel Byte Order weiter oben.

Eine C#-spezifische Möglichkeit ist, die Serialisierung/Deserialsierung aus den Knoten und Attribut-Fachklassen ganz herauszuhalten und in Extension Methods auszulagern. Macht man gerne dann, wenn Fachklasse nichts von der Serialisierung/Deserialsierung kennt und umgekehrt. Ist wiederum übertrieben, wenn es Interfaces und Klassen aus System.IO sind, die kann man immer schmerzfrei referenzieren.
Zuletzt geändert von Roland Ziegler am 14.03.2016 20:02:32, insgesamt 2-mal geändert.

Benutzeravatar
F. Schn.
Beiträge: 6630
Registriert: 24.10.2011 18:58:26

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#13 Beitrag von F. Schn. »

Ok, dann habe ich es noch nicht ganz verstenden: Was hilft mir die Festlegung der Zusi-Doku auf IntelByteOrder = LittleEndian, wenn mir .Net keine Byte-Reinfolge garantieren kann?
Diese Signatur möchte folgendes bekannter machen: ZusiWiki · ZusiSK: Streckenprojekte · YouTube: Objektbau für Zusi · euirc: Zusi-Chat

Benutzeravatar
Roland Ziegler
Beiträge: 5508
Registriert: 04.11.2001 22:09:26
Wohnort: 32U 0294406 5629020
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#14 Beitrag von Roland Ziegler »

Da Du direkt auf TCP aufsetzt und TCP für die Payload keinerlei Codierung kennt - ursprünglich zur byte-weisen Textübertragung gedacht - und die .Net-Socket-Klassen auch nichts wegnehmen oder hinzufügen, erhältst Du die Daten exakt so, wie der Sender sie verschickt. Und der benutzt Little Endian. (Das ist vollkommen unabhängig davon, dass beim Socket-Verbindungsaufbau und in den TCP-Headern Big Endian genormt ist. Aber über den Dateninhalt weiß TCP nichts.)

(Es gibt auf TCP aufsetzende Protokolle, die in der Paketschicht die Endianness angeben und entsprechend beide erlauben, z.B. IIOP von CORBA, aber hier ist das alles etwas simpler.)

Benutzeravatar
F. Schn.
Beiträge: 6630
Registriert: 24.10.2011 18:58:26

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#15 Beitrag von F. Schn. »

Klar, wenn wir uns Gedanklich vom Protokoll bis zum PC bewegen, bleiben die Daten bis zum Lesen Little Endian.

Aber der Datentyp int hat ja Systemintern keine garantierte Endianness. Was ja mich erst mal nicht interressiert, weil ich in den Datentyp int ja bewusst nicht "hineinschaue", also die einzelnen Bytes im Speicher gar nicht sehen muss und kann. Zum Problem wird das aber, wenn der Bitkonverter dies aufhebt und dadurch die verschiedenen Möglichkeiten, wie int intern repräsentiert ist, auch nach außen getragen werden. Denn Rechnen mit Zahlen, Elemente indizieren, Meldungen ausgeben usw. passiert ja alles unter dem Einfluss der System-Endianness.

Nun habe ich also PC-Intern eine variable Endianness und im TCP-Protokoll eine fixe Endianness. Und niemand konvertiert dazwischen. Weder die BitConverter-Klasse, noch die BinaryReader/Writer-Klassen. Also sind selbige für diesen Zweck in meinen Augen unbrauchbar. Einwände?
Diese Signatur möchte folgendes bekannter machen: ZusiWiki · ZusiSK: Streckenprojekte · YouTube: Objektbau für Zusi · euirc: Zusi-Chat

Benutzeravatar
Jens Haupert
Beiträge: 4911
Registriert: 23.03.2004 14:44:34
Aktuelle Projekte: http://www.zusidisplay.de
Wohnort: Berlin
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#16 Beitrag von Jens Haupert »

Hui-jui-jui,

hier wird wieder die Welt bis zum Elementarsten aufgedröselt. 8o Bei .NET ist die Welt doch so einfach. ZusiDisplay macht folgendes (falls das jemand interessiert; es funktioniert bestens seit über 7 Jahren):

1.) Socket anlegen und verbinden
2.) Neue Instanz "NetworkStream" <- die bekommt den Socket als Argument
3.) Darum einen "BinaryReader" wrappen und auslesen
4.) Gelesene Bytes mit "BitConverter" in die entsprechenden Typen umwandeln ==> :sonne

Geht alles mit Bordmitteln. Konfigurieren muss man da nichts. Das Einzige was nicht richtig funktioniert, sind die Umlaute in Strings. Dazu hab ich schon vieles probiert, .NET liefert wohl nicht die von Delphi genutzte Codierung frei Haus mit. Es geht aber auch so.

Grüße
Jens
Zuletzt geändert von Jens Haupert am 15.03.2016 09:45:34, insgesamt 3-mal geändert.

Benutzeravatar
Roland Ziegler
Beiträge: 5508
Registriert: 04.11.2001 22:09:26
Wohnort: 32U 0294406 5629020
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#17 Beitrag von Roland Ziegler »

Jens, was macht denn der BitConverter bei Dir, was der BinrayReader nicht schon selbst erledigen kann?

Ich würde vermutlich trotzdem von BinaryReader ableiten, um das protokoll-proprietäre String-Format auszulesen und dort innen drin eine Encoding-Klasse instantieren, vermutlich ist es ja CP1252, 8859-1 oder -15.

Benutzeravatar
Jens Haupert
Beiträge: 4911
Registriert: 23.03.2004 14:44:34
Aktuelle Projekte: http://www.zusidisplay.de
Wohnort: Berlin
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#18 Beitrag von Jens Haupert »

Roland Ziegler hat geschrieben:Jens, was macht denn der BitConverter bei Dir, was der BinrayReader nicht schon selbst erledigen kann?
Guter Einwand, den Umweg kann man sich in der Tat schenken. :tup Stammt wohl noch aus der Anfangszeit, als das Protokoll nach und nach umgestellt wurde und einige Typen noch im Fluss waren. Der erste Teil der Pipeline hab ich dann seit Jahren nicht mehr verändert, nachdem er's tat.
Roland Ziegler hat geschrieben:Ich würde vermutlich trotzdem von BinaryReader ableiten, um das protokoll-proprietäre String-Format auszulesen und dort innen drin eine Encoding-Klasse instantieren, vermutlich ist es ja CP1252, 8859-1 oder -15.
Ja, ich vermute CP1252. Die 8859er ISOs hatte ich mal getestet, das war's glaub ich nicht. Schau ich mir vielleicht nochmal an.

Grüße
Jens

Benutzeravatar
Jens Haupert
Beiträge: 4911
Registriert: 23.03.2004 14:44:34
Aktuelle Projekte: http://www.zusidisplay.de
Wohnort: Berlin
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#19 Beitrag von Jens Haupert »

Nur nochmal die Rückmeldung: es ist CP1252, welches man leicht hiermit erhalten kann:

Code: Alles auswählen

var encoding = Encoding.GetEncoding(1252);
Grüße
Jens

Andreas Karg
Beiträge: 4718
Registriert: 28.04.2002 12:56:00
Kontaktdaten:

Re: Zusi 3 TCP-Protokoll-Implementation für .Net

#20 Beitrag von Andreas Karg »

ToDo fuer alle Auslaender & Nutzer fremdlaendischer Maschinen wie mich selber:
Mal checken, ob die Codepage irgendwie von den Systemeinstellungen zusammenhaengt.
Ich hatte neulich mit Z2 noch Probleme, weil mein System auf UK eingestellt war und nicht auf Deutsch. Hat dem Simulator die Kommas in den Fliesskommazahlen verhagelt...

Antworten