Sockets: Unterschied zwischen den Versionen
PhilKa (Diskussion | Beiträge) Die Seite wurde neu angelegt: „= Socket-Programmierung in C = Die '''Socket-Programmierung''' in C ermöglicht die Kommunikation zwischen Prozessen über ein Netzwerk. Sie bildet die Grundlage vieler Internetanwendungen wie Webserver, Chatprogramme oder Dateitransfers. Obwohl C keine "Socket-Klasse" im objektorientierten Sinne besitzt, wird der Begriff oft verwendet, um die Funktionalität rund um die ''Socket-API'' zu beschreiben, die über Header-Dateien wie <code><sys/socket.h&…“ |
PhilKa (Diskussion | Beiträge) |
||
| Zeile 212: | Zeile 212: | ||
--- | --- | ||
= Zusammenspiel von socket(), listen() und accept() = | |||
Die Funktionen '''socket()''', '''listen()''' und '''accept()''' gehören zur Berkeley-Socket-API und werden verwendet, um in C oder C++ eine TCP/IP-Verbindung zwischen einem Server und einem Client aufzubauen. | |||
Sie befinden sich in der Header-Datei <code><sys/socket.h></code> und werden unter UNIX/Linux-Systemen genutzt. | |||
== Übersicht == | |||
{| class="wikitable" | |||
! Funktion !! Zweck | |||
|- | |||
| <code>socket()</code> || Erstellt einen neuen Kommunikationsendpunkt (Socket) | |||
|- | |||
| <code>listen()</code> || Versetzt den Socket in den Wartemodus für eingehende Verbindungen | |||
|- | |||
| <code>accept()</code> || Akzeptiert eine eingehende Verbindung und erstellt einen neuen Socket für den Client | |||
|} | |||
== 1. socket() == | |||
Erstellt einen neuen Socket und liefert einen Dateideskriptor zurück. | |||
<syntaxhighlight lang="cpp"> | |||
int socket(int domain, int type, int protocol); | |||
</syntaxhighlight> | |||
=== Parameter === | |||
* <code>domain</code> – Protokollfamilie, z. B.: | |||
** <code>AF_INET</code> für IPv4 | |||
** <code>AF_INET6</code> für IPv6 | |||
* <code>type</code> – Art der Verbindung: | |||
** <code>SOCK_STREAM</code> für TCP | |||
** <code>SOCK_DGRAM</code> für UDP | |||
* <code>protocol</code> – normalerweise <code>0</code> (Standardprotokoll) | |||
=== Rückgabewert === | |||
Ein Dateideskriptor (int) für den Socket oder <code>-1</code> bei Fehler. | |||
=== Beispiel === | |||
<syntaxhighlight lang="cpp"> | |||
int sockfd = socket(AF_INET, SOCK_STREAM, 0); | |||
if (sockfd < 0) { | |||
perror("socket failed"); | |||
exit(1); | |||
} | |||
</syntaxhighlight> | |||
== 2. listen() == | |||
Versetzt einen TCP-Socket in den Server-Wartemodus. Der Socket muss vorher mit <code>bind()</code> an eine IP-Adresse und einen Port gebunden sein. | |||
<syntaxhighlight lang="cpp"> | |||
int listen(int sockfd, int backlog); | |||
</syntaxhighlight> | |||
=== Parameter === | |||
* <code>sockfd</code> – Socket-Dateideskriptor (von <code>socket()</code>) | |||
* <code>backlog</code> – maximale Anzahl wartender Verbindungen in der Warteschlange | |||
=== Rückgabewert === | |||
<code>0</code> bei Erfolg, <code>-1</code> bei Fehler. | |||
=== Beispiel === | |||
<syntaxhighlight lang="cpp"> | |||
if (listen(sockfd, 5) < 0) { | |||
perror("listen failed"); | |||
exit(1); | |||
} | |||
</syntaxhighlight> | |||
== 3. accept() == | |||
Akzeptiert eine eingehende Verbindung und erstellt einen neuen Socket für die Kommunikation mit dem Client. | |||
<syntaxhighlight lang="cpp"> | |||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | |||
</syntaxhighlight> | |||
=== Parameter === | |||
* <code>sockfd</code> – der lauschende Socket (aus <code>listen()</code>) | |||
* <code>addr</code> – Zeiger auf eine Struktur, die die Adresse des Clients enthält | |||
* <code>addrlen</code> – Zeiger auf die Länge der Adressstruktur | |||
=== Rückgabewert === | |||
Ein neuer Socket-Deskriptor (<code>int</code>) für die Client-Verbindung oder <code>-1</code> bei Fehler. | |||
=== Beispiel === | |||
<syntaxhighlight lang="cpp"> | |||
struct sockaddr_in clientAddr; | |||
socklen_t addrlen = sizeof(clientAddr); | |||
int newsockfd = accept(sockfd, (struct sockaddr*)&clientAddr, &addrlen); | |||
if (newsockfd < 0) { | |||
perror("accept failed"); | |||
exit(1); | |||
} | |||
</syntaxhighlight> | |||
== Gesamtbeispiel: Einfacher TCP-Server == | |||
<syntaxhighlight lang="cpp"> | |||
#include <iostream> | |||
#include <sys/socket.h> | |||
#include <netinet/in.h> | |||
#include <unistd.h> | |||
int main() { | |||
int sockfd = socket(AF_INET, SOCK_STREAM, 0); | |||
if (sockfd < 0) { perror("socket"); return 1; } | |||
sockaddr_in serverAddr{}; | |||
serverAddr.sin_family = AF_INET; | |||
serverAddr.sin_addr.s_addr = INADDR_ANY; | |||
serverAddr.sin_port = htons(8080); | |||
if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { | |||
perror("bind"); | |||
return 1; | |||
} | |||
if (listen(sockfd, 5) < 0) { | |||
perror("listen"); | |||
return 1; | |||
} | |||
std::cout << "Server wartet auf Verbindungen..." << std::endl; | |||
sockaddr_in clientAddr{}; | |||
socklen_t addrlen = sizeof(clientAddr); | |||
int clientSock = accept(sockfd, (struct sockaddr*)&clientAddr, &addrlen); | |||
if (clientSock < 0) { | |||
perror("accept"); | |||
return 1; | |||
} | |||
std::cout << "Verbindung hergestellt!" << std::endl; | |||
::close(clientSock); | |||
::close(sockfd); | |||
} | |||
</syntaxhighlight> | |||
== Quellen == | |||
* [https://man7.org/linux/man-pages/man2/socket.2.html socket(2) – Linux Man Page] | |||
* [https://en.cppreference.com/w/cpp/header/sys/socket.h cppreference.com: <sys/socket.h>] | |||
== Siehe auch == | == Siehe auch == | ||
Aktuelle Version vom 30. Oktober 2025, 11:30 Uhr
Socket-Programmierung in C
Die Socket-Programmierung in C ermöglicht die Kommunikation zwischen Prozessen über ein Netzwerk. Sie bildet die Grundlage vieler Internetanwendungen wie Webserver, Chatprogramme oder Dateitransfers.
Obwohl C keine "Socket-Klasse" im objektorientierten Sinne besitzt, wird der Begriff oft verwendet, um die Funktionalität rund um die Socket-API zu beschreiben, die über Header-Dateien wie <sys/socket.h> und <netinet/in.h> bereitgestellt wird.
Grundlagen
Ein Socket ist eine Schnittstelle (Endpunkt) für die Kommunikation zwischen zwei Rechnern über ein Netzwerk. In C werden Sockets über Dateideskriptoren (int-Werte) dargestellt, ähnlich wie Dateien.
Typische Kommunikation:
Client <----> Server
---
Wichtige Funktionen der Socket-API
1. socket()
Erzeugt einen neuen Socket.
int socket(int domain, int type, int protocol);
- domain – Kommunikationsdomäne, z. B.:
*AF_INETfür IPv4 *AF_INET6für IPv6
- type – Typ des Sockets:
*SOCK_STREAM(TCP) *SOCK_DGRAM(UDP)
- protocol – Meist
0(Standardprotokoll für Typ)
- Beispiel:**
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
---
2. bind()
Verknüpft den Socket mit einer lokalen Adresse (z. B. Port).
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
- Beispiel (Server):**
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(8080);
bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
---
3. listen()
Versetzt den Socket in den "Lauschmodus" für eingehende Verbindungen (nur TCP).
int listen(int sockfd, int backlog);
---
4. accept()
Nimmt eine eingehende Verbindung an.
int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
---
5. connect()
Verbindet einen Client-Socket mit einem Server.
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
---
6. send() / recv()
Dient dem Senden und Empfangen von Daten über TCP.
ssize_t send(int sockfd, const void* buf, size_t len, int flags);
ssize_t recv(int sockfd, void* buf, size_t len, int flags);
---
7. close()
Schließt den Socket.
close(sockfd);
---
Beispiel: Einfacher TCP-Server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[1024] = {0};
const char* message = "Hallo vom Server!";
// Socket erstellen
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// Adresse zuweisen
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
bind(server_fd, (struct sockaddr*)&address, sizeof(address));
// Auf Verbindungen warten
listen(server_fd, 3);
printf("Server wartet auf Verbindung...\n");
// Verbindung annehmen
new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
printf("Client verbunden!\n");
// Daten empfangen und antworten
read(new_socket, buffer, sizeof(buffer));
printf("Client sagt: %s\n", buffer);
send(new_socket, message, strlen(message), 0);
close(new_socket);
close(server_fd);
return 0;
}
---
Beispiel: Einfacher TCP-Client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
// Socket erstellen
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// IP-Adresse des Servers konvertieren
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
// Verbindung herstellen
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
// Nachricht senden
send(sock, "Hallo Server!", strlen("Hallo Server!"), 0);
// Antwort empfangen
read(sock, buffer, sizeof(buffer));
printf("Server antwortet: %s\n", buffer);
close(sock);
return 0;
}
---
Ablauf einer TCP-Verbindung
Server: socket() → bind() → listen() → accept() Client: socket() → connect() Beide: send()/recv() Beide: close()
---
Zusammenspiel von socket(), listen() und accept()
Die Funktionen socket(), listen() und accept() gehören zur Berkeley-Socket-API und werden verwendet, um in C oder C++ eine TCP/IP-Verbindung zwischen einem Server und einem Client aufzubauen.
Sie befinden sich in der Header-Datei <sys/socket.h> und werden unter UNIX/Linux-Systemen genutzt.
Übersicht
| Funktion | Zweck |
|---|---|
socket() |
Erstellt einen neuen Kommunikationsendpunkt (Socket) |
listen() |
Versetzt den Socket in den Wartemodus für eingehende Verbindungen |
accept() |
Akzeptiert eine eingehende Verbindung und erstellt einen neuen Socket für den Client |
1. socket()
Erstellt einen neuen Socket und liefert einen Dateideskriptor zurück.
int socket(int domain, int type, int protocol);
Parameter
domain– Protokollfamilie, z. B.:AF_INETfür IPv4AF_INET6für IPv6
type– Art der Verbindung:SOCK_STREAMfür TCPSOCK_DGRAMfür UDP
protocol– normalerweise0(Standardprotokoll)
Rückgabewert
Ein Dateideskriptor (int) für den Socket oder -1 bei Fehler.
Beispiel
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket failed");
exit(1);
}
2. listen()
Versetzt einen TCP-Socket in den Server-Wartemodus. Der Socket muss vorher mit bind() an eine IP-Adresse und einen Port gebunden sein.
int listen(int sockfd, int backlog);
Parameter
sockfd– Socket-Dateideskriptor (vonsocket())backlog– maximale Anzahl wartender Verbindungen in der Warteschlange
Rückgabewert
0 bei Erfolg, -1 bei Fehler.
Beispiel
if (listen(sockfd, 5) < 0) {
perror("listen failed");
exit(1);
}
3. accept()
Akzeptiert eine eingehende Verbindung und erstellt einen neuen Socket für die Kommunikation mit dem Client.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Parameter
sockfd– der lauschende Socket (auslisten())addr– Zeiger auf eine Struktur, die die Adresse des Clients enthältaddrlen– Zeiger auf die Länge der Adressstruktur
Rückgabewert
Ein neuer Socket-Deskriptor (int) für die Client-Verbindung oder -1 bei Fehler.
Beispiel
struct sockaddr_in clientAddr;
socklen_t addrlen = sizeof(clientAddr);
int newsockfd = accept(sockfd, (struct sockaddr*)&clientAddr, &addrlen);
if (newsockfd < 0) {
perror("accept failed");
exit(1);
}
Gesamtbeispiel: Einfacher TCP-Server
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) { perror("socket"); return 1; }
sockaddr_in serverAddr{};
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(8080);
if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
perror("bind");
return 1;
}
if (listen(sockfd, 5) < 0) {
perror("listen");
return 1;
}
std::cout << "Server wartet auf Verbindungen..." << std::endl;
sockaddr_in clientAddr{};
socklen_t addrlen = sizeof(clientAddr);
int clientSock = accept(sockfd, (struct sockaddr*)&clientAddr, &addrlen);
if (clientSock < 0) {
perror("accept");
return 1;
}
std::cout << "Verbindung hergestellt!" << std::endl;
::close(clientSock);
::close(sockfd);
}
Quellen
Siehe auch
- getaddrinfo (C-Funktion)
- bind (C-Funktion)
- connect (C-Funktion)
- send (C-Funktion)
- recv (C-Funktion)
- TCP/IP-Modell
- UDP (Protokoll)
Quellen
- Stevens, W. Richard: UNIX Network Programming, Vol. 1, Prentice Hall.
- ISO/IEC 9899:2018 – Programming Language C
- GNU/Linux man pages:
man 2 socket,man 2 bind,man 2 connect