Unix Domain Sockets: Unterschied zwischen den Versionen

Aus dev.kaibel.net
Zur Navigation springen Zur Suche springen
Die Seite wurde neu angelegt: „= Unix Domain Sockets = '''Unix Domain Sockets''' (auch '''Local Sockets''' oder '''AF_UNIX-Sockets''') sind eine Form der Interprozesskommunikation (IPC) unter Unix-ähnlichen Betriebssystemen (Linux, macOS, BSD). Im Gegensatz zu Internet-Sockets (z. B. TCP/UDP über IPv4 oder IPv6) ermöglichen Unix Domain Sockets eine **schnelle und sichere Kommunikation zwischen Prozessen auf demselben System**. --- == Grundprinzip == Unix Domain Sockets verwende…“
 
Keine Bearbeitungszusammenfassung
 
(Eine dazwischenliegende Version desselben Benutzers wird nicht angezeigt)
Zeile 2: Zeile 2:


'''Unix Domain Sockets''' (auch '''Local Sockets''' oder '''AF_UNIX-Sockets''') sind eine Form der Interprozesskommunikation (IPC) unter Unix-ähnlichen Betriebssystemen (Linux, macOS, BSD).   
'''Unix Domain Sockets''' (auch '''Local Sockets''' oder '''AF_UNIX-Sockets''') sind eine Form der Interprozesskommunikation (IPC) unter Unix-ähnlichen Betriebssystemen (Linux, macOS, BSD).   
Im Gegensatz zu Internet-Sockets (z. B. TCP/UDP über IPv4 oder IPv6) ermöglichen Unix Domain Sockets eine **schnelle und sichere Kommunikation zwischen Prozessen auf demselben System**.
Im Gegensatz zu Internet-Sockets (z. B. TCP/UDP über IPv4 oder IPv6) ermöglichen Unix Domain Sockets eine ''schnelle und sichere Kommunikation zwischen Prozessen auf demselben System''.


---
---
Zeile 8: Zeile 8:
== Grundprinzip ==
== Grundprinzip ==
Unix Domain Sockets verwenden das Dateisystem als Namensraum:   
Unix Domain Sockets verwenden das Dateisystem als Namensraum:   
Jeder Socket wird durch einen **Dateipfad** (z. B. <code>/tmp/socket</code>) repräsentiert.
Jeder Socket wird durch einen ''Dateipfad'' (z. B. <code>/tmp/socket</code>) repräsentiert.


Prozesse können über diesen Pfad eine Verbindung aufbauen und bidirektional Daten austauschen – ähnlich wie über Netzwerk-Sockets, jedoch **ohne Netzwerkprotokoll-Overhead**.
Prozesse können über diesen Pfad eine Verbindung aufbauen und bidirektional Daten austauschen – ähnlich wie über Netzwerk-Sockets, jedoch ''ohne Netzwerkprotokoll-Overhead''.


<pre>
<pre>
Zeile 25: Zeile 25:


== Eigenschaften ==
== Eigenschaften ==
* Kommunikation **nur lokal** (kein Routing über Netzwerke)
* Kommunikation ''nur lokal'' (kein Routing über Netzwerke)
* Sehr **geringe Latenz** und **hohe Geschwindigkeit**
* Sehr ''geringe Latenz'' und ''hohe Geschwindigkeit''
* Unterstützt **Stream (SOCK_STREAM)** und **Datagram (SOCK_DGRAM)**-Typen
* Unterstützt ''Stream (SOCK_STREAM)'' und ''Datagram (SOCK_DGRAM)''-Typen
* Nutzung von **Dateisystemrechten** zur Zugriffskontrolle
* Nutzung von ''Dateisystemrechten'' zur Zugriffskontrolle
* Ermöglicht **Dateideskriptor-Weitergabe** (Advanced IPC)
* Ermöglicht ''Dateideskriptor-Weitergabe'' (Advanced IPC)


---
---
Zeile 184: Zeile 184:
socklen_t len = sizeof(client);
socklen_t len = sizeof(client);
recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &len);
recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &len);
printf("Empfange
printf("Empfangen: %s\n", buf);
sendto(fd, "Antwort vom Server", 18, 0, (struct sockaddr*)&client, len);
</syntaxhighlight>
 
Client:
<syntaxhighlight lang="c">
int fd;
struct sockaddr_un addr, srv;
char buf[100];
 
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/client_dgram.sock");
unlink(addr.sun_path);
bind(fd, (struct sockaddr*)&addr, sizeof(addr));
 
srv.sun_family = AF_UNIX;
strcpy(srv.sun_path, "/tmp/server_dgram.sock");
 
sendto(fd, "Hallo Server", 12, 0, (struct sockaddr*)&srv, sizeof(srv));
recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
printf("Antwort: %s\n", buf);
</syntaxhighlight>
 
---
 
== Zugriffsschutz ==
Unix Domain Sockets nutzen das ''Dateisystem-Rechtesystem''. 
Nur Prozesse mit ausreichenden Rechten (z. B. Besitzer, Gruppe, `chmod`-Berechtigungen) dürfen sich verbinden. 
Das macht sie sicherer als Netzwerk-Sockets für lokale Kommunikation.
 
---
 
== Leistung ==
Da keine Protokollkonvertierung (IP, Routing, Checksummen etc.) notwendig ist, sind Unix Domain Sockets ''deutlich schneller'' als TCP/IP-Sockets auf demselben Rechner. 
Sie erreichen Übertragungsraten ähnlich wie anonyme Pipes oder Shared Memory, bieten aber zugleich ''vollwertige bidirektionale Kommunikation''.
 
---
 
== Unterschiede zu TCP/IP-Sockets ==
{| class="wikitable"
! Merkmal !! Unix Domain Socket !! TCP/IP Socket
|-
| Namensraum || Dateipfad || IP-Adresse + Port
|-
| Reichweite || nur lokal || systemübergreifend
|-
| Sicherheit || durch Dateirechte || durch Firewalls/Netzwerkebene
|-
| Geschwindigkeit || sehr hoch || langsamer (Netzwerk-Stack)
|-
| Protokoll || kein IP/Transport-Layer || TCP oder UDP
|-
| Debugging || via `ls`, `lsof` || via `netstat`, `ss`
|}
 
---
 
== Einsatzgebiete ==
* Kommunikation zwischen ''Daemon'' und ''Client'' (z. B. <code>systemd</code>, <code>dbus</code>)
* ''Datenbanken'' (z. B. PostgreSQL, MySQL) 
* ''Container-Kommunikation'' (z. B. Docker Socket: <code>/var/run/docker.sock</code>) 
* ''Lokale IPC'' zwischen GUI-Programmen und Hintergrunddiensten
 
---
 
== Vorteile ==
* Sehr schnell und effizient 
* Sicherheit über UNIX-Dateisystemrechte 
* Keine Netzwerkkonfiguration nötig 
* Unterstützt alle Socket-APIs (send, recv, select, poll, etc.)
 
== Nachteile ==
* Nur lokale Kommunikation 
* Kein Routing über Netzwerk 
* Dateipfade müssen verwaltet und ggf. gelöscht werden 
 
---
 
== Siehe auch ==
* [[Socket (Programmierung)]]
* [[TCP (Protokoll)]]
* [[UDP (Protokoll)]]
* [[Interprozesskommunikation (IPC)]]
* [[Named Pipe (FIFO)]]
* [[POSIX Threads]]
* [[Systemaufrufe unter Unix]]
 
---
 
== Quellen ==
* Stevens, W. Richard: ''UNIX Network Programming, Vol. 1'', Prentice Hall 
* IEEE Std 1003.1 (POSIX) – Sockets API 
* Linux Man Pages: <code>man 7 unix</code>, <code>man 2 socket</code> 
* GNU C Library Documentation 
* The Linux Programming Interface – Michael Kerrisk, 2010

Aktuelle Version vom 21. Oktober 2025, 15:03 Uhr

Unix Domain Sockets

Unix Domain Sockets (auch Local Sockets oder AF_UNIX-Sockets) sind eine Form der Interprozesskommunikation (IPC) unter Unix-ähnlichen Betriebssystemen (Linux, macOS, BSD). Im Gegensatz zu Internet-Sockets (z. B. TCP/UDP über IPv4 oder IPv6) ermöglichen Unix Domain Sockets eine schnelle und sichere Kommunikation zwischen Prozessen auf demselben System.

---

Grundprinzip

Unix Domain Sockets verwenden das Dateisystem als Namensraum: Jeder Socket wird durch einen Dateipfad (z. B. /tmp/socket) repräsentiert.

Prozesse können über diesen Pfad eine Verbindung aufbauen und bidirektional Daten austauschen – ähnlich wie über Netzwerk-Sockets, jedoch ohne Netzwerkprotokoll-Overhead.

+-------------+             +-------------+
|  Prozess A  | <---------> |  Prozess B  |
| (Client)    |             | (Server)    |
+-------------+             +-------------+
          \                   /
           \_________________/
             Unix Domain Socket (/tmp/demo.sock)

---

Eigenschaften

  • Kommunikation nur lokal (kein Routing über Netzwerke)
  • Sehr geringe Latenz und hohe Geschwindigkeit
  • Unterstützt Stream (SOCK_STREAM) und Datagram (SOCK_DGRAM)-Typen
  • Nutzung von Dateisystemrechten zur Zugriffskontrolle
  • Ermöglicht Dateideskriptor-Weitergabe (Advanced IPC)

---

Socket-Typen

Typ Beschreibung Entspricht
SOCK_STREAM zuverlässige, verbindungsorientierte Kommunikation ähnlich wie TCP
SOCK_DGRAM verbindungslos, Nachrichten-orientiert ähnlich wie UDP
SOCK_SEQPACKET sequenziell, aber paketorientiert Hybridform

---

Header und Adressstruktur

#include <sys/socket.h>
#include <sys/un.h>

Adresse einer Unix-Socket-Verbindung:

struct sockaddr_un {
    sa_family_t sun_family;    // AF_UNIX
    char sun_path[108];        // Pfadname des Sockets
};

---

Beispiel 1: Server mit Unix Domain Stream Socket

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCKET_PATH "/tmp/unix_demo.sock"

int main() {
    int server_fd, client_fd;
    struct sockaddr_un addr;
    char buffer[128];

    unlink(SOCKET_PATH); // alten Socket-Pfad löschen

    if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);

    if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 5) == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("Server wartet auf Verbindung...\n");
    client_fd = accept(server_fd, NULL, NULL);
    if (client_fd == -1) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    read(client_fd, buffer, sizeof(buffer));
    printf("Nachricht vom Client: %s\n", buffer);

    const char* reply = "Hallo vom Server!";
    write(client_fd, reply, strlen(reply));

    close(client_fd);
    close(server_fd);
    unlink(SOCKET_PATH); // Socket-Datei entfernen
    return 0;
}

---

Beispiel 2: Client

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCKET_PATH "/tmp/unix_demo.sock"

int main() {
    int sock;
    struct sockaddr_un addr;
    char buffer[128];

    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);

    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("connect");
        exit(EXIT_FAILURE);
    }

    const char* message = "Hallo Server!";
    write(sock, message, strlen(message));

    int n = read(sock, buffer, sizeof(buffer) - 1);
    buffer[n] = '\0';
    printf("Antwort vom Server: %s\n", buffer);

    close(sock);
    return 0;
}

---

Beispiel 3: Datagram-Variante (SOCK_DGRAM)

Bei SOCK_DGRAM ist keine Verbindung nötig. Client und Server tauschen Nachrichten ähnlich wie UDP aus.

Server:

int fd;
struct sockaddr_un addr;
char buf[100];

fd = socket(AF_UNIX, SOCK_DGRAM, 0);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/server_dgram.sock");
unlink(addr.sun_path);
bind(fd, (struct sockaddr*)&addr, sizeof(addr));

struct sockaddr_un client;
socklen_t len = sizeof(client);
recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &len);
printf("Empfangen: %s\n", buf);
sendto(fd, "Antwort vom Server", 18, 0, (struct sockaddr*)&client, len);

Client:

int fd;
struct sockaddr_un addr, srv;
char buf[100];

fd = socket(AF_UNIX, SOCK_DGRAM, 0);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/client_dgram.sock");
unlink(addr.sun_path);
bind(fd, (struct sockaddr*)&addr, sizeof(addr));

srv.sun_family = AF_UNIX;
strcpy(srv.sun_path, "/tmp/server_dgram.sock");

sendto(fd, "Hallo Server", 12, 0, (struct sockaddr*)&srv, sizeof(srv));
recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
printf("Antwort: %s\n", buf);

---

Zugriffsschutz

Unix Domain Sockets nutzen das Dateisystem-Rechtesystem. Nur Prozesse mit ausreichenden Rechten (z. B. Besitzer, Gruppe, `chmod`-Berechtigungen) dürfen sich verbinden. Das macht sie sicherer als Netzwerk-Sockets für lokale Kommunikation.

---

Leistung

Da keine Protokollkonvertierung (IP, Routing, Checksummen etc.) notwendig ist, sind Unix Domain Sockets deutlich schneller als TCP/IP-Sockets auf demselben Rechner. Sie erreichen Übertragungsraten ähnlich wie anonyme Pipes oder Shared Memory, bieten aber zugleich vollwertige bidirektionale Kommunikation.

---

Unterschiede zu TCP/IP-Sockets

Merkmal Unix Domain Socket TCP/IP Socket
Namensraum Dateipfad IP-Adresse + Port
Reichweite nur lokal systemübergreifend
Sicherheit durch Dateirechte durch Firewalls/Netzwerkebene
Geschwindigkeit sehr hoch langsamer (Netzwerk-Stack)
Protokoll kein IP/Transport-Layer TCP oder UDP
Debugging via `ls`, `lsof` via `netstat`, `ss`

---

Einsatzgebiete

  • Kommunikation zwischen Daemon und Client (z. B. systemd, dbus)
  • Datenbanken (z. B. PostgreSQL, MySQL)
  • Container-Kommunikation (z. B. Docker Socket: /var/run/docker.sock)
  • Lokale IPC zwischen GUI-Programmen und Hintergrunddiensten

---

Vorteile

  • Sehr schnell und effizient
  • Sicherheit über UNIX-Dateisystemrechte
  • Keine Netzwerkkonfiguration nötig
  • Unterstützt alle Socket-APIs (send, recv, select, poll, etc.)

Nachteile

  • Nur lokale Kommunikation
  • Kein Routing über Netzwerk
  • Dateipfade müssen verwaltet und ggf. gelöscht werden

---

Siehe auch

---

Quellen

  • Stevens, W. Richard: UNIX Network Programming, Vol. 1, Prentice Hall
  • IEEE Std 1003.1 (POSIX) – Sockets API
  • Linux Man Pages: man 7 unix, man 2 socket
  • GNU C Library Documentation
  • The Linux Programming Interface – Michael Kerrisk, 2010