Unix Domain Sockets
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: <syntaxhighlight lang="c"> 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("Empfange