Inhalt
Topic:.InterProcessComm_Jc.
..
Topic:.InterProcessComm_Jc.Req.
...
Topic:.InterProcessComm_Jc.Req.WhereToUse.
Ein Prozess ist dadurch gekennzeichnet, dass er in einem bestimmten Speicherraum auf einem Prozessorboard abläuft. Ein Prozess kann mehrere Threads umfassen. Das ist die allgemeine Definition eines Prozesses (=> Wikipedia). Die hier vorgestellte Interprozess-Kommunikation widmet sich einem allgemeinen Ansatz sowohl auf dem PC als auch auf beliebigen Embedded Systemen / Echtzeitsteuerungen mit beliebiger Betriebssystem-Basis. Der Ansatz soll allgemein gehalten werden.
Ein Prozess soll einem anderen Prozess zu einem beliebigem Zeitpunkt Daten übergeben oder ein Ereignis auslösen, der andere Prozess wartet in einem bestimmten Thread (einer Task eines Realtime-Operationsystems) auf die Daten / das Ereignis. Für die Interprozesskommunikation selbst wird jedes Kommunikationsereignis als "einzeln" bewertet. Der Zusammenhang zwischen den Kommunikationsereignissen wird in der Anwenderprogrammierung hergestellt. Das entspricht im bekannten OSI-Modell der Kommunikation der Schnittstelle zwischen Schicht 4 (Verbindungs- oder Übertragungsschicht) zu den höheren und Schichten 5 bis 7 (Sitzungsschicht bis Applikation).
Für die Anwendung der Interprozesskommunikation soll es nicht von wesentlichen Belang sein, ob die Prozesse, die miteinander kommunizieren sollen, sich auf dem selben CPU-Board befinden, oder sich in räumlich eng benachbarten CPU-Boards befinden (in einem Rahmen) oder räumlich getrennt sind. Für Prozesse auf einem CPU-Board können beispielsweise in einer Realtime-Systemumgebung optimal schnelle Kommunikationsmechanismen bestehen, die auf einem gemeinsamen Speicherraum aufbauen. Um die Algorithmen aber auf dem PC zu testen, kann man auf die optimal schnelle Kopplung verzichten. Dann kann eine Interprozesskommunikation mit einer anderen Realisierung benutzt werden, ohne dass die anwendende Software modifiziert werden braucht. Wenn beispielsweise Prozesse im Zielsystem auf Prozessorkarten in einem Rahmen laufen, dann kann gegebenenfalls auch eine Dualport-RAM-Kopplung die Wahl sein. Wenn aber auch ein schnelles Ethernet zur Verfügung steht, dann kann die Interprozesskopplung wiederum ohne Anpassung in der Anwendersoftware auf Ethernet umgelenkt werden. Einige Übertragungseigenschaften wie Übertragungszeit ändern sich, die grundlegende Herangehensweise bleibt aber identisch. Somit kann die Wahl der physischen Verbindung unabhängig von der Anwender-Softwarerealisierung getroffen werden. Lediglich die Implementierung der Interprozesskommunikation selbst muss der Hardwareauswahl entsprechen.
Gleichzeitig ist diese Art der Interprozesskommunikation immer ab der definierten Schnittstelle in Richtung Anwendung betriebssystemunabhängig.
Topic:.InterProcessComm_Jc.Req.Solutions.
Konkret ausgeführt ist hier eine Interprozess-Kommunikation über Sockets in C++ unter Windows und in Java. Ein einfaches Beispiel für die Gestaltung der Interprozesskommunikation mittels Dual-Port-RAM ist ebenfalls angegeben.
Der Schnittstellen der Interprozesskommunikation sind so gehalten, dass beispielsweise auf einem PC unter Verwendung von Sockets simuliert werden kann, was im Zielsystem mit anderen Mitteln realisiert wird, ohne Änderung der Quellen des Anwenderprogrammes. Lediglich die passende Library muss jeweils dazugebunden werden beziehungsweise die Instanziierung der ausführenden Klassen (Module in C) muss beim Hochlauf entsprechend erfolgen.
Gleichzeitig wird hier eine Implementierung der Socketkommunikation geboten, die recht einfach zu handhaben ist: Grundsätzlich ist dasjenige, was eine Socketkommunikation zu leisten hat, vielfältig und komplex. Die Systemaufrufe müssen alle Anforderungen unterstützen und sind daher naturgemäß nicht unkompliziert. Die Implementierung der Socketkommunikation nach den hier beschriebenen Prinzipien legt um die Systemaufrufe (java.net.* bzw. Windows-API) eine Schale, die nach außen eine wesentlich vereinfachte Schnittstelle anbietet.
Topic:.InterProcessComm_Jc.CommonlyApprouch.
Um eine allgemeingültige Schnittstelle einer Interprozesskommunikation festzulegen, sind generelle Überlegungen notwendig welchen Ansprüchen diese Kommunikation genügen muss.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Nicht vorausgesetzt werden darf, dass die Socketkommunikation immer anwendbar ist, wenn es um Interprozesskommunikation geht. Die Socketkommunikation ist zwar ein moderner und relativ universeller Ansatz, halbwegs bis gut standardisiert auf allen Systemen unter Windows, Unix/Linux und vielen anderen einsetzbar, aber es gibt Fälle, bei denen man Interprozesskommunikation nicht mit Sockets ausführen will. Dafür kann es mehrere Gründe geben.Alternativen für eine Interprozesskommunikation sind beispielsweise eine Dual-Port-Ram-Kopplung über Prozessorboard-Grenzen, eine Kommunikation mehrere Prozesse, die einen gemeinsamen RAM haben (beispielsweise shared memory unter Windows) oder Speziallösungen der Kommunikation.
Die Idee der hier vorgestellten Interprozesskommunikations-Schnittstellen ist eine allgemein verwendbare Herangehensweise an alle diese Möglichkeiten. Ein wichtiger Effekt dabei ist, dass man beispielsweise auf dem PC mittels Socketkommunikation das simulativ testen kann, was später in der Ziel-Plattform mittels Dual-Port-RAM-Kopplung verwirklicht wird.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Kennzeichnend für die Interprozesskommunikation ist, dass auf Daten gewartet wird. "auf Daten" und "gewartet" sind hier zwei vollkommen verschiedene Aspekte. Es bedeutet also, dass Daten übergeben werden, und dass die Daten erwartet werden. Es muss demzufolge einen Thread geben, der wartet, bis Daten eintreffen. Dieser Thread ist ein Teil des Empfängerprozesses. Was mit den Daten dann gemacht wird, ist nicht Gegenstand dieses Artikels. Möglicherweise können die Daten in eine Warteliste für andere Threads eingetragen werden, oder es werden unmittelbar Aktionen ausgeführt.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Es gibt ein zweites Prinzip, das in der Praxis ebenfalls recht häufig vorkommt: Der Empfänger fragt zyklisch, beispielsweise in einem Regelungszyklus ab, ob Daten vorhanden sind. Wenn ja, dann holt er diese ab. Das ist beispielsweise bei einer Dual-Port-RAM-Kopplung ober beim Datenaustausch über den RAM typisch: Es wird ein Begleitbit gesetzt, wenn Daten vorhanden sind. Dieses wird abgefragt.
Die Interprozesskommunikation muss für die Variante Socketkommunkation beide Empfangsprinzipien können. Da die Socketkommunikation an sich nach dem Prinzip "warten" funktioniert, wird die Polling-Variante mit einem eigenem Empfangsthread realisiert. Für einen Einsatz auf einer Zielplattform wird möglicherweise nur eines beider Prinzipien (Polling oder Warten) benutzt. Die jeweils andere Methode wird dann nicht implementiert.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Mit einem einzeln betrachteten Kommunikationsereignis werden eher kurze Daten übergeben. Die Beschränkung bei einem UDP-Telegramm liegt bei etwa 1400 Byte. Diese Datenmenge wird von UDP garantiert gebündelt übertragen. Wenn man bei der Nutzungsplanung der Interprozesskommunikation diese Größe als Maximum ansetzt, sind viele Anforderungen erfüllbar. Ist es notwendig, größere Datenmengen zu transportieren, dann kann bei einer Socket-Implementierung auf TCP aufgesetzt werden. Andere Kommunikationsmechanismen kennen ebenfalls bestimmte Grenzen. Von der Schnittstelle her ist der Datenumfang nicht begrenzt, die Begrenzung liegt also zwischen Implementierung und den dazu notwendigerweise passenden Anwenderanforderungen.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Es gibt mehrere Ansätze, je nach den System- und Hardwaregegebenheiten. Alle Ansätze sind von der Interprozesskommunikations-Schnittstelle realisierbar:
Übergabe in einem festen Speicherbereich. Dabei ist vorausgesetzt, dass Sender- und Empfängerprozess auf den selben Speicher zugreifen können. Das ist beispielsweise der Fall bei einer Dual-Port-Ram-Kopplung oder wenn keine Speicherschutzmechanismen (Protected mode) zwischen verschiedenen Prozessen auf dem selben CPU-Board existieren. Eine weitere Möglichkeit ist der sogenannte "shared Memory" zwischen Prozessen in einem PC unter Windows. Hierbei handelt es sich dennoch um eine Prozesskommunikation und nicht um eine Kommunikation zwischen Threads eines Prozesses. Im letzteren Fall ist ein gemeinsamer Speicher, unter Beachtung von Mutex-Problemen, selbstverständlich. Im ersten Fall ist das eine Möglichkeit unter bestimmten Verhältnissen.
Übergabe als UDP-IP-Telegramm über Netzwerk oder auch als "localhost". Das ist die einfachste Möglichkeit unter Nutzung von Sockets. Die Länge eines UDP-IP-Telegramms ist meist auf ca. 1400 Byte begrenzt. Für die meisten Erfordernisse solcher Zwecke ist das jedoch ausreichend, daher eine solche Lösung opportun. Werden längere Daten benötigt, dann muss entweder auf TCP-IP umgestellt werden (Nutzung der Datensicherung bei Übertragung mehrerer Einzelblöcke), oder eine einfache UDP-Lösung, die mehrere Telegramme zusammenfasst und dann erst als empfangen weitergibt.
Übergabe in einem File lokal oder auf einem Netzwerk. Das ist die Lösung, wenn ein (eventuell älteres) Programmierwerkzeug keine Socket.Kommunikation kennt. Der sendende Prozess schreibt einen File mit bestimmten Namen an eine bestimmte Stelle oder trägt in einen vorhandenen File (am Anfang) eine Kennung ein. Der empfangende Prozess liest den File und wertet ihn aus. Die Daten stehen im File, die Tatsache, dass der File existiert oder einen bestimmten Inhalt hat, kennzeichnet den Zeitpunkt der Übertragung.
Insbesondere aus den Überlegungen der RAM- und Dualport-RAM-Kopplung unter den Bedingungen der Rechenzeiteffektivität ist
es nicht geboten, für den Empfang von Daten einen Ziel-Speicherbereich anzubieten, in den die Daten hineinkopiert werden sollen.
Stattdessen soll die Referenz auf die Daten aus dem Empfangsroutinenaufruf receive()
von innen heraus geliefert werden. Die verarbeitende Routine kann dann auf die Daten direkt zugreifen, muss aber den Speicherbereich
der Interprozesskommunikation nach Verwertung wieder zurückgeben. Es kann sein, dass es sich um einen festen Speicherbereich
handelt, insbesondere im Embedded-Control-Bereich. Es kann sein, insbesondere bei Socketkommunikation auf PC, dass die Empfangsroutine
innerhalb der Implementierung der Interprozesskommunikation den Speicherbereich allokiert. Für die Freigabe des Speicherbereiches
aus Anwendersicht muss die Interprozesskommunikation eine Routine anbieten: freeData()
.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Beide Varianten sind bei der Socketkommunikation der OSI-Schicht bekannt:
UDP (Datagramm-Socket) ist verbindungslos, es kann von jeder Quelle empfangen werden und an jedes Ziel gesendet werden.
TCP (Stream-Socket) ist verbindungsorientiert. Ist die Kommunikation geöffnet, erfolgt sie nur mit einem bestimmten Partner. Damit kann auch eine Übertragung eines Datenstromes in mehreren Einzeltelegrammen und eine Quittierung/Fehlerkorrektur auf der Ebene des TCP-Treibers erfolgen.
Das Prinzip ist verallgemeinerbar:
Bei einer verbindungslosen Kommunikation muss bei jedem Sendeaufruf ein Adressat angegeben werden. Es können beliebige Partner, die mit der physischen Kommunikation erreichbar sind, angesprochen werden. Aber die zu übertragende Information muss mit diesem Sendeaufruf abgeschlossen sein. Meist ist damit die Datenmenge begrenzt. Für eine dauerhafte Verbindung muss die Anwendung selbst sorgen. Außerdem muss der Absender einer empfangenen Information beim Empfangsaufruf erfasst werden.
Bei einer verbindungsorientierten Kommunikation steht der Adressat mit Öffnen der Verbindung fest. Nur damit ist es möglich, eine beliebig lange Information zu übertragen.
Beide Prinzipien müssen berücksichtigt werden.
Ein höherer Anspruch ist die Realisierung von ServerSockets mit diesem Kommunikationsinterface. Dazu wird folgendes Prinzip angeboten:
Der Server ist zunächst eine verbindungslose Kommunikation, der auf Anfragen wartet. Wird eine Anfrage emfangen (receive()
), dann wird damit die Absenderadresse bekanntgegeben. Mit der bekannten Absenderadresse wird dann auf einem neuen Kanal eine
verbindungsorientierte Kommunikation aufgebaut.
Topic:.InterProcessComm_Jc.CommonlyApprouch..
Bei Kommunikationsaufgaben über phyische Medien können Fehler auftreten. Fehlerursachen sind dabei vielfältig und in Systemanordnungen zu suchen. Ein allgemeiner Kommunikationsansatz unabhängig von der physischen und Treiber-Implementierungsschicht kann nicht auf bestimmte oder besondere Fehler dieser Schichten in der Applikation reagieren wollen. Demzufolge ist folgendes Prinzip geboten:
Fehler, die in der Implementierung der Interprozesskommunikation sinnvoll abfangbar sind, sollen dort behandelt werden und dem Anwender nicht gemeldet werden. Eine möglicherweise geforderte Protokollierung ist innerhalb der Interprozesskommunikationsimplementierung vorzunehmen. Fehler solcher Art sind beispielsweise ein Fehlschlagen eines Aufrufes wegen einer kurzen Blockierung, Mutex und ähnliches, bei dem ein automatisch wiederholter Aufruf hilft.
Fehler, die in der Implementierungsschicht nicht behandelt werden, sollen dem Anwender im quasi-Klartext gemeldet werden. Der Anwender soll aber keine speziellen Behandlungsroutinen auf bestimmte Fehler einbauen sondern lediglich eine Gesamtbehandlung ausführen. Diese ist oft über Bedienerentscheidungen führbar.
Beispiel: Eine Verbindung soll geöffnet werden, der Bediener hat die Verbindung selbst ausgewählt, das Öffnen erfolgt nach Mausklick in einer GUI. Die Fehlermeldung wird im Klartext angezeigt. Beispielsweise hat sich der Bediener bei der Angabe des Kommunikationsziels geirrt oder ein Treiber muss erst nachgestartet werden. Diese richtige Handlungsentscheidung kann der Bediener aus Gesamtsystemkenntnis treffen.
Beispiel: Eine parametrierte Verbindung soll geöffnet werden, das geschieht in einem bedienfreien System. Ein auftretender Fehler wird protokolliert, das öffnen der Verbindung wird dann zyklisch in längeren Zeitabständen (Sekunden...) wiederholt. Gegebenenfalls wird die Fehlermeldung in einer Zentrale empfangen (Diagnosesystem), dort wird der Verbindungspartner repariert, die Verbindung wird dann wegen der zyklischen Wiederholung aufgebaut, sobald dies möglich ist.
Die fehlermeldenden Methoden liefern als Fehlerinformation zunächst nur eine Integer-Nummer, meist negativ, zurück. Über eine einheitliche Übersetzungsroutine zugehörig zur Implementierungsschicht kann diese Nummer dann in einen Klartext gewandelt werden, und zwar möglicherweise umschaltbar auf verschiedene Sprachen mit einem besonderen Umschalter der Implementierung (nicht in der Schnittstelle enthalten). Es kann aber auch zweckmäßig sein, den Fehlercode zu übertragen und erst in einem Anzeigeprozess in Klartext zu wandeln. Dazu ist vorzusehen, dass die Zuordnung Fehlernummer - Klartext passend zur Implementierung in einem XML-File gehalten wird. Der Fehlercode soll positiv und negativ identisch sein und als Betrag interpretiert werden.
Topic:.InterProcessComm_Jc.InterfaceSpecification.
Für die Interprozesskommunikation soll eine Schnittstelle definiert werden, die auf öffnen, schließen, senden und warten auf Empfangsdaten ausgerichtet ist, kurz als open-send-receive-close zu bezeichnen. Diese Schnittstelle soll in gleichartiger Weise für C, C++ und Java verfügbar sein und insbesondere auch diese Programmierwelten, die in verschiedenen zu kommunizierenden Prozessen verwendet werden können, verbinden. Eine Implementierung dieser Schnittstelle für C, C++ und Java für eine Socketkommunikation oder andere Kommunikationsmechanismen ist unabhängig von der Frage nach der Schnittstelle selbst.
Das Factory-Pattern soll verwendet werden: Adress-Objekte und Kommunikationsobjekte werden mittels einer Factoryklasse bereitgestellt. Damit kann der innere Aufbau der Implementierung innerhalb der von den zusammenpassenden Factory-Methoden gelieferten Instanzen aufeinander abgestimmt sein, ohne dass das außen beachtet werden muss. In C++ ist damit ein static_cast für die Ableitung der abstrakten Klassen auf die Instanziierungsklassen ausreichend, in C ist ein direktes Pointercasting anwendbar. Voraussetzung hierbei ist, dass alle Objekte von einer gemeinsamen Factoryklasse gebildet werden.
Topic:.InterProcessComm_Jc.InterfaceSpecification..
Zum Senden und Empfangen sind Adressen notwendig. Handelt es sich um eine Socketkommunikation, dann würde eine Adresse aus IP-Nummer und Port bestehen. Jedoch ist die Kommunikation wie oben beschrieben nicht auf die Socketkommunikation beschränkt, die Adress-Schnittstelle daher allgemeiner gehalten. Die Adress-Schnittstelle selbst ist lediglich eine Vorwärtsdeklaration in C und in C++ und Java ein leeres Interface (Marker-Interface). Damit sind auf Anwenderebene (an der Schnittstelle) keine Festlegungen über den Datenaufbau einer Adresse getroffen.
Instanzen von Adressen werden von der Factory-Klasse der Interprozesskommunikation angelegt. Die Factoryklasse bietet eine ebenfalls allgemeingültige Methode zur Anlage, die in der Implementierungsschicht konkretisiert wird:
Es wird ein numerischer Parameter und eine Zeichenkette übergeben, aus der jede beliebige vorprogrammierte Adresse gebildet werden kann. Der String-Parameter soll mit einem kennzeichenden Teil beginnen wie "UDP:", "TCP:" oder "DualPortRAM:". Welche Varianten hier zulässig sind, ist nicht in der Schnittstellenspezifikation festgelegt sondern in der Implementierung. Damit kann sich der Anwender in seiner Programmierung auch nicht auf eine Festlegung stützen. Er wird den String-Parameter aus einer Projektierung, Konfiguration oder Bedienerangabe entnehmen, die dem Umfeld (damit der konkret verwendeten Implementierung) entspricht. Der numerische Parameter ist adäquat zu sehen, seine Bedeutung hängt einerseits an der Implementierung und andererseit an der Bedeutungsauswahl im Zeichenkettenparameter. Es ist damit beispielsweise ein Handle übergebbar, oder eine Thread-oder Queue-Identnummer.
Beispiele:
//TCP-Verbindung auf bestimmtes Port InterProcessComm_Factory::create(0,"TCP://146.192.80.123:50022"); //UDP-Verbindung ohne Angabe einer Adresse: Receive auf allen Verbindungen auf angegebenes Port InterProcessComm_Factory::create(0xF002,"UDP:") //Verbindung als http herstellen, auch für diese Schicht kann das Interface verwendet werden. InterProcessComm_Factory::create(0,"http://www.destination.org") //Verbindung über RAM-Speicher InterProcessComm_Factory::create(handleRAM,"RAM")
Die jeweilige Implementierung entscheidet über Zulässigkeit und Verwendung. Wenn eine nicht zulässige Adresse angegeben wird, wird keine Instanz angelegt, es wird null zurückgegeben. Eine spezielle Fehlermeldung erfolgt nicht.
Topic:.InterProcessComm_Jc.InterfaceSpecification..
Die Instanziierung erfolgt mittels Aufruf der statischen Methode
Der Typ der dabei übergebenen eigenen Adresse muss in der Implementierung die richtige Instanz auswählen. Es ist denkbar und sinnvoll, die Interprozesskommunikation gleichzeitig für verschiedene Medien anzubieten. Die Auswahl erfolgt also bei der Adressfestlegung.
Bei der Instanziierung sollen noch keine Kommunikationsressourcen angespochen, getestet oder verwendet werden. Es ist also zulässig, die Instanziierung bereits zu einem Zeitpunkt auszuführen, zu dem beispielsweise Treiber der Kommunikationsschichten noch nicht geladen sind. Damit können bei der Instanziierung auch keine Kommunikationsfehler festgestellt werden. Lediglich die entsprechenden Speicherbereiche werden reserviert und initialisiert.
Topic:.InterProcessComm_Jc.InterfaceSpecification..
Die Schnittstelle der Interprozesskommunikation ist in Java ein Interface. In C++ ist es eine abstrakte Klasse in der Rolle eines Interfaces. In C kann entweder ein quasi-Interface unter Nutzung von virtuellen Methoden gebildet werden, in diesem Falle wären mehrere Implementierungen gleichzeitig zur Runtime möglich, oder es handelt sich um einfache Funktions-Prototypen, die in entsprechenden Sources oder einer Library erfüllt werden.
Folgend sind die Methoden der Schnittstelle angegeben. Bei syntaktischen Unterschieden steht die C++ - und Java-Formulierung untereinander. Die Unterschiede sind nur syntaktischer Natur, Semantik und Pragmatik sind identisch.
Eröffnung der Kommunikation. Das entspricht dem Einrichten eines Briefkastens. Ab jetzt können Telegramme einlaufen. Die dstAddress (Empfängeradresse) muss dann angegeben zu werden, wenn es sich um eine verbindungsorientierte Kommunikation handelt. Bei einer verbindungslosen Kommunikation soll diese Adresse als Defaultwert gespeichert werden, falls beim send()-Aufruf keine Adresse übergeben wird. Ansonsten wird sie ignoriert, eine null-Referenz ist zulässig.
Bei open() wird im Argument isBlocking angegeben, ob die receive-Methode blockieren soll, wenn keine Daten vorliegen, oder zurückkehren mit einem null-Zeiger. Diese Auswahl gilt bis close().
Mit dem open()-Aufruf sollen die Kommunikationsressourcen belegt werden, die Kommunikation wird geprüft. Folglich können hier
Fehler auftreten. Der Fehlercode wird als Returnwert numerisch zurückgeliefert. Es ist übersetzbar in einen Klartext mittest
getErrorMessage(int)
. Ist der Aufruf fehlerhaft, dann soll er ohne ein voriges close() wiederholt werden können. Ist der Aufruf erfolgreich, dann
wird 0 zurückgeliefert. Der Fehlercode selbst soll nicht algorithmisch verwertet werden. Es ist als Bedienerinfo oder als
Meldung verwertbar. Wenn ein open() fehlschlägt, dann kann es sinnvoll sein, dieses automatisch zyklisch in angemessenem Abständen
zu wiederholen. Es wird dann erfolgreich sein, wenn eine äußere Fehlerursache abgestellt ist. Oder es erfolgt ein manueller
Eingriff unter Benachrichtigung des Bedieners mit einer Klartextfehlermeldung.
Beenden der Kommunikation. Alle Datenübertragungsressourcen werden freigegeben. Die Instanz kann für andere Kommunikationsaufgaben oder später nach einem erneuten open() weiter verwendet werden. Im Normalfall wird 0 zurückgegeben. Ungleich 0 ist ein Fehlercode.
Senden einer Information. Es wird eine Referenz auf die Daten, die Byteanzahl und der Adressat angegeben. Die Methode darf nur kurzzeitig blocken, wenn die Daten momentan aus Mutex-Gründen nicht abgesetzt werden können, die Kommunikation aber an sich eingerichtet ist. Der Returnwert gibt im positiven Fall die Anzahl der gesendeten Bytes zurück. Wird ein negativer Wert zurückgegeben, dann ist das Senden nicht möglich. Die Bedeutung des Rückgabewertes im Fehlerfall hängt von der Implementierungsplattform ab und kann mit der Methode getErrorMessage() in einen Klartext gewandelt werden. Ein Fehler-Returnwert soll nicht algorithmisch verwertet werden, sondern nur für eine Fehlerangabe genutzt. Wenn kein Senden möglich ist, obwohl der open-Aufruf zuvor erfolgreich war, dann kann nur die Kommunikation gestört sein. Entweder das Senden wird automatisch nach einer angemessenen Zeit wiederholt, oder die Kommunikation wird geschlossen und erneut geöffnet.
Kann die Information erfolgreich abgesetzt werden, dann kehrt die Methode mit positivem Returnwert zurück. Damit ist nicht unbedingt gewährleistet, dass die Information auch tatsächlich beim Empfänger angekommen ist. Lediglich das Senden unter den normalen gegebenen Umständen kann vorausgesetzt werden, sprich: Es gibt zunächst keinen Grund, einen Fehler zu vermuten. Möglich ist es, dass ein erster Sendeaufruf sofort ohne Fehlermeldung zurückkehrt, da die Informationen erfolgreich an die Treiberschicht übergeben werden konnten. Ist aber die Verbindung gestört, dann wird das gegebenenfalls erst bei weiteren Sende- oder Empfangsaufrufen bemerkt. Es obliegt der Anwendung, die tatsächlich stattfindende Kommunikation zu überwachen, das ist Aufgabe der OSI-Schicht 5.
Erwarten des Empfanges einer Information. Die Methode blockt dann, wenn das im open-Aufruf das so festgelegt wurde und aktuell keine empfangenen Informationen vorliegen. Das Blockieren erfolgt solange, bis entweder etwas empfangen wird oder abortReceive() oder close() gerufen wurde. Wenn im Treiber bereits empfangene Informationen gespeichert vorliegen, blockt die Methode nicht.
Die Methode kehrt sofort zurück, liefert einen null-Zeiger und auf nrofBytes den Wert 0 zurück, wenn keine Daten vorliegen und der nicht-blockierende Modus bei open() angegeben wurde.
Zurückgegeben wird eine Referenz auf einen Speicher, der die Daten enthält. Dabei soll gewährleistet sein, dass dieser Speicher bis zum Aufruf von freeData() stabil bleibt. Der Speicher wird intern beim Empfang angelegt und muss mit freeData() wieder freigegeben werden. Es kann sich beispielsweise um einen internen Empfangsbuffer handeln, oder um die Datenquelle selbst, wenn beispielsweise ein shared-Memory-Zugriff oder in einem Dualport-RAM realisiert wird. Mit der Übergabe der Referenz auf die Daten von innen ist ein Kopieren von Daten nicht zwingend notwendig, insbesondere für schnelle Kommunikation in kleinen System werden damit Ressources gespart. Dafür ist aber der extra Freigabeaufruf relinguishData() als Eigenschaft der Schnittstelle notwendig.
In nrofBytes[0] wird die Anzahl der empfangenen Bytes zurückgegeben, oder ein Fehlercode (negativ), wenn der Empfang nicht möglich ist. Ist diese Anzahl = 0 entweder im blockierendem Modus oder wenn eine Referenz auf einen Speicher zurückgegeben wurde, dann bedeutet dass, das zwar etwas erfolgreich empfangen wurde, aber ohne Information. Der Speicher muss dennoch freigegeben werden.
Die übergeben Referenz auf sender wird mit den Absenderdaten gefüllt. Deren Inhalt kann verglichen werden mit einer Zieladeresse. oder beim Senden als Zieladresse angegeben werden. Die Referenz darf null sein, wenn die Absenderadresse nicht interessiert, insbesondere bei verbindungsorientierter Kommunikation.
Bei einem Fehler kehrt der Aufruf zurück. In nrofBytes[0] steht ein negativer Wert. Die Fehlerursache kann textuell für eine Bedienermitteilung mit getErrorMessage() abgefragt werden.
Mit Aufruf dieser Methode in einem beliebigen Thread wird ein blockierender receive()-Aufruf beendet. Das ist beispielsweise als Folge einer Handeingabe sinnvoll oder nach Ablauf eines Timeout. Die Methode liefert im Normalfall 0 oder einen Fehlercode zurück.
Mit diesem Aufruf werden die bei receive() übergebene Daten wieder freigegeben.
Diese Methode übersetzt eine Fehlernummer in einen Klartext. Die Fehlernummer kann ein Rückgabewert von open(), close(), send(), receive() oder abortReceive() sein. Die Fehlernummer ist als implementierungsinterne Konstante zu interpretieren und außen nicht numerisch auszuwerten. Der Klartext soll die entsprechende Bedeutung in der Implementierung für einen Bediener lesbar ausgegeben.
Diese Methode dient dem Austesten einer bei receive() gelieferten Absenderadresse. Es ist der Vergleich mit einer bekannten Zieladresse möglich.
Topic:.InterProcessComm_Jc.InterfaceSpecification..
Dieser XML-File soll nach folgendem Schema aufgebaut sein:
<ipc:InterProcessComm-ErrorMsg xmlns:ipc="www.vishia.org/InterProcessComm_V1"> <ipc:msg ident="123"> <ipc:msgText language="en">english message</ipc:msgText> <ipc:msgText language="de">Deutsche Fehlerbeschreibung</ipc:msgText> </ipc:msg> <ipc:msg ident="254"> <ipc:msgText language="en">english message</ipc:msgText> <ipc:msgText language="de">Deutsche Fehlerbeschreibung</ipc:msgText> </ipc:msg> </ipc:InterProcessComm-ErrorMsg>
Sprachen sind beliebig wählbar, die Kürzel sollen den international üblichen Kürzeln für das www entsprechen. Bei den Fehlernummern sind hier nur positive Werte anzugeben. Negative Returnwerte aus Methoden sind in positive zu negieren.
Topic:.InterProcessComm_Jc.ImplementationJava.
Die Implementierung der Socketkommunikation in Java ist unter Nutzung der java.net-Klassen DatagrammSocket und StreamSocket unter in den Klassen srcJava_vishiaRun/org/vishia/communication/InterProcessComm_SocketImpl, srcJava_vishiaRun/org/vishia/communication/Adress_InterProcessComm_Socket und srcJava_vishiaRun/org/vishia/communication/InterProcessCommFactorySocket implementiert. Die Quellen sind als open-source nach der LPGL-Lizenz nutzbar. LPGL ist die Lesser Gnu Public License und bedeutet, dass mit Nutzung der open-source-Quellen der Java-Interprozesskommunikation nicht deswegen das gesamte nutzende Programm open-source sein muss. Da die Interprozesskommunikation der geringste und recht allgemeingültige Teil des Anwenderprogramms sein wird, ist also kein Nachteil einer ungewollten Offenlegung vorhanden. Bilaterale Sondervereinbarungen können auch den Status der LPGL für diese Sourcen ändern, so dass ein Nutzer auch nicht von der Nutzung dieser Software informiert werden braucht.