InterProcessComm

InterProcessComm

Inhalt


1 InterProzessKommunikation

Topic:.InterProcessComm_Jc.

..


1.1 Aufgabenstellung

Topic:.InterProcessComm_Jc.Req.

...


1.1.1 Allgemeiner Ansatz der Interprozesskommunikation

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.


1.1.2 Lösungen

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.


1.2 Die allgemeine Herangehensweise

Topic:.InterProcessComm_Jc.CommonlyApprouch.

Um eine allgemeingültige Schnittstelle einer Interprozesskommunikation festzulegen, sind generelle Überlegungen notwendig welchen Ansprüchen diese Kommunikation genügen muss.


1.2.1 Socketkommunikation ist zwar universell, aber nicht immer voraussetzbar

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.


1.2.2 Prinzip Empfänger wartet auf Daten

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.


1.2.3 Prinzip Empfänger pollt, ob Daten vorhanden sind

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.


1.2.4 Datenumfang

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.


1.2.5 Wie werden Daten übergeben?

Topic:.InterProcessComm_Jc.CommonlyApprouch..

Es gibt mehrere Ansätze, je nach den System- und Hardwaregegebenheiten. Alle Ansätze sind von der Interprozesskommunikations-Schnittstelle realisierbar:

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().


1.2.6 Verbindungsorientierte oder verbindungslose Kommunikation

Topic:.InterProcessComm_Jc.CommonlyApprouch..

Beide Varianten sind bei der Socketkommunikation der OSI-Schicht bekannt:

Das Prinzip ist verallgemeinerbar:

Beide Prinzipien müssen berücksichtigt werden.

Ein höherer Anspruch ist die Realisierung von ServerSockets mit diesem Kommunikationsinterface. Dazu wird folgendes Prinzip angeboten:


1.2.7 Fehlerbehandlung

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:

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.


1.3 Schnittstellengestaltung

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.


1.3.1 Adress-Schnittstellen

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:

InterprocessComm_Address* InterProcessComm_Factory::create(int32 nAddressParam, const char* sAddressParam); //C++
InterprocessComm_Address InterProcessComm_Factory.create(int nAddressParam, String sAddressParam); //Java

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.


1.3.2 Instanziierung der InterProcessComm

Topic:.InterProcessComm_Jc.InterfaceSpecification..

Die Instanziierung erfolgt mittels Aufruf der statischen Methode

InterProcessComm* InterProcessComm_Factory::createInterProcessComm(Address_InterProcessComm* ownAddress);

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.


1.3.3 Methoden der Interprozesskommunikations-Schnittstelle

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.

int open( Address_InterProcessComm const* dstAddress, boolean isBlocking);
int open( Address_InterProcessComm dstAddress, bool isBlocking);

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.

int close();

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.

int send( void* data, int nBytes, Address_InterProcessComm const* addressee);
int send( byte[] data, int nBytes, Address_InterProcessComm addressee);

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.

void* receive ( int* nrofBytes , Address_InterProcessComm* sender);
byte[] receive ( int[] nrofBytes , Address_InterProcessComm sender);

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.

int abortReceive();

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.

freeData(void* data);
freeData(byte[] data);

Mit diesem Aufruf werden die bei receive() übergebene Daten wieder freigegeben.

const char* getErrorMessage(int errorNumber);
String getErrorMessage(int errorNumber);

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.

bool equals( Address_InterProcessComm* sender, Address_InterProcessComm* address);
boolean equals( Address_InterProcessComm sender, Address_InterProcessComm address);

Diese Methode dient dem Austesten einer bei receive() gelieferten Absenderadresse. Es ist der Vergleich mit einer bekannten Zieladresse möglich.


1.3.4 XML-File für Fehlertext-Nummern-Zuordnung

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.


1.4 Implementierung in Java

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.