Rpcgen – Interne Funktionsweise
rpcgen – Interne Funktionsweise
Diese Seite beschreibt die interne Arbeitsweise des Werkzeugs rpcgen und wie es auf niedriger Ebene die Kommunikation zwischen Client und Server über das Netzwerk mit Hilfe von Remote Procedure Calls (RPC) realisiert.
Sie ergänzt den Artikel rpcgen (C-Werkzeug) und erklärt insbesondere, wie rpcgen:
- RPC-Code generiert,
- Datenstrukturen in übertragbare Formate (XDR) wandelt,
- Stub-Funktionen für Client und Server erzeugt,
- und wie die eigentliche Netzwerkkommunikation technisch abläuft.
---
Architekturüberblick
rpcgen ist ein Code-Generator für das ONC-RPC-System (*Open Network Computing Remote Procedure Call*), ursprünglich von Sun Microsystems entwickelt. Es setzt auf drei Schichten auf:
+--------------------------+ | Benutzerprogramm | (Client / Server Implementierung) +--------------------------+ | RPC-Stubs (von rpcgen) | (Client-Stub, Server-Stub) +--------------------------+ | XDR & RPC-Laufzeit | (libc / libtirpc) +--------------------------+ | Transport (UDP/TCP) | +--------------------------+
---
1. Der rpcgen-Codegenerator
rpcgen verarbeitet eine Schnittstellenbeschreibung (Datei *.x*) und erzeugt daraus automatisch mehrere C-Dateien:
| Datei | Beschreibung |
|---|---|
name.h |
Enthält Funktionsprototypen und Konstanten (Program-, Versions- und Prozedur-IDs) |
name_xdr.c |
Enthält Funktionen zur XDR-Datenkonvertierung |
name_clnt.c |
Enthält Client-Stubs für RPC-Aufrufe |
name_svc.c |
Enthält Server-Stubs, die eingehende RPCs verarbeiten |
---
2. XDR – External Data Representation
RPC verwendet das XDR-Format (External Data Representation), um Daten plattformunabhängig zu übertragen.
Jede Struktur, die in der .x-Datei definiert ist, erhält automatisch eine passende XDR-Funktion:
bool_t xdr_structname(XDR* xdrs, struct structname* objp);
Die Funktion arbeitet je nach Modus:
- **ENCODE** – Daten werden in Netzwerkformat serialisiert
- **DECODE** – Daten werden aus Netzwerkformat deserialisiert
Beispiel:
bool_t xdr_intpair(XDR *xdrs, intpair *objp) {
return xdr_int(xdrs, &objp->a) &&
xdr_int(xdrs, &objp->b);
}
Damit können Systeme mit unterschiedlicher Endianness (Little/Big Endian) sicher kommunizieren.
---
3. Die generierten Stubs
rpcgen erzeugt zwei Stub-Schichten:
Client-Stubs (name_clnt.c)
Diese Funktionen sehen für den Programmierer wie lokale Funktionsaufrufe aus, führen intern aber eine Netzwerkübertragung aus.
Beispiel:
int *add_1(intpair *argp, CLIENT *clnt) {
static int res;
memset(&res, 0, sizeof(res));
if (clnt_call(clnt, ADD,
(xdrproc_t)xdr_intpair, (caddr_t)argp,
(xdrproc_t)xdr_int, (caddr_t)&res,
TIMEOUT) != RPC_SUCCESS) {
return NULL;
}
return &res;
}
Hier ruft clnt_call() die RPC-Laufzeitfunktion aus der Bibliothek libtirpc auf, die:
1. die Daten per XDR kodiert,
2. über UDP oder TCP an den Server sendet,
3. auf die Antwort wartet,
4. das Ergebnis dekodiert und zurückgibt.
---
Server-Stubs (name_svc.c)
Diese Funktionen verarbeiten eingehende RPC-Anfragen. Sie werden automatisch von der Funktion svc_run() aufgerufen, sobald ein Client eine RPC-Anfrage sendet.
Beispiel:
static void calcprog_1(struct svc_req *rqstp, SVCXPRT *transp) {
union {
intpair add_1_arg;
} argument;
int result;
bool_t retval = FALSE;
memset(&argument, 0, sizeof(argument));
if (!svc_getargs(transp, (xdrproc_t)xdr_intpair, (caddr_t)&argument)) {
svcerr_decode(transp);
return;
}
result = *add_1_svc(&argument, rqstp);
svc_sendreply(transp, (xdrproc_t)xdr_int, (char*)&result);
}
---
4. Ablauf einer RPC-Kommunikation
Client Server --------------------------------------------------------- | add_1(&p) | | | → clnt_call() | | | → send via UDP/TCP | | | | svc_run() empfängt | | | → svc_getargs() | | | → add_1_svc() | | | → svc_sendreply() | | ← Ergebnis empfangen | | ---------------------------------------------------------
- Kurz gesagt:**
- Der Client ruft eine Stub-Funktion auf. - Der Stub serialisiert Argumente und sendet sie an den Server. - Der Server-Stub empfängt, dekodiert, ruft die echte Funktion auf und schickt das Ergebnis zurück.
---
5. Transport und Protokolle
rpcgen unterstützt mehrere Transportarten:
- **UDP** – schnell, verbindungslos, nicht zuverlässig
- **TCP** – zuverlässig, verbindungsorientiert
- **RAW** – intern für Tests
Die Bibliothek `libtirpc` (oder ältere `libc`-Implementierungen) übernimmt den Netzwerkcode vollständig. Beispiel:
CLIENT *clnt = clnt_create("localhost", CALCPROG, CALCVERS, "tcp");
---
6. Der Portmapper
Damit Client und Server einander finden, nutzt ONC-RPC den Portmapper-Dienst (Programmnummer 100000, Port 111). Der Server registriert sich beim Portmapper:
svc_register(transp, CALCPROG, CALCVERS, calcprog_1, IPPROTO_TCP);
Der Client fragt beim Portmapper den tatsächlichen Port für das Programm CALCPROG ab.
Dadurch kann RPC auch dynamische Ports verwenden.
---
7. Lebenszyklus eines rpcgen-Projekts
1. .x-Datei definieren (Datentypen & Prozeduren) 2. rpcgen aufrufen → erzeugt Code 3. Server-Implementierung schreiben (z. B. *_svc.c erweitern) 4. Client-Programm schreiben 5. Beide kompilieren und starten 6. Client ruft Funktionen auf → RPC läuft automatisch über Netzwerk
---
8. Fehlerbehandlung und Rückgabecodes
RPC-Funktionen geben in der Regel über enum clnt_stat oder enum auth_stat Fehler zurück, z. B.:
RPC_SUCCESS– ErfolgRPC_TIMEDOUT– TimeoutRPC_AUTHERROR– AuthentifizierungsfehlerRPC_CANTSEND– Senden fehlgeschlagen
Fehlerausgabe erfolgt meist über:
clnt_perror(clnt, "Fehler bei RPC");
---
9. Vergleich mit modernen Technologien
| Technologie | Beschreibung | |--------------|--------------| | **ONC RPC (rpcgen)** | Klassisches C-basiertes RPC-System | | **gRPC (Google RPC)** | Moderne, Protobuf-basierte Variante mit HTTP/2 | | **XML-RPC / JSON-RPC** | Textbasierte, plattformunabhängige Alternativen | | **D-Bus** | IPC für Linux-Desktop-Systeme |
rpcgen ist sehr performant, aber weniger flexibel für heterogene oder moderne Webumgebungen.
---
Siehe auch
- rpcgen (C-Werkzeug)
- XDR (External Data Representation)
- Marshalling (Informatik)
- Stub (Softwareentwicklung)
- Portmapper (RPC)
- Verteilte Systeme
Quellen
- Sun Microsystems: rpcgen User’s Guide
- Stevens, W. Richard: UNIX Network Programming, Vol. 1, Prentice Hall.
- Linux Manual:
man rpcgen,man 3 rpc - RFC 5531 – Open Network Computing (ONC) Remote Procedure Call (RPC)