Was ist Socket-Programmierung?
Socket-Programmierung ist eine Möglichkeit, zwei Knoten in einem Netzwerk zu verbinden, um miteinander zu kommunizieren. Ein Socket (Knoten) lauscht an einem bestimmten Port an einer IP, während der andere Socket auf den anderen zugreift, um eine Verbindung herzustellen. Der Server bildet den Listener-Socket, während der Client den Server kontaktiert.
Zustandsdiagramm für Server- und Client-Modell

Zustandsdiagramm für Server- und Client-Modell von Socket
Stufen für Server
Der Server wird mit den folgenden Schritten erstellt:
Entwurfsmuster für die Fabrikmethode
1. Socket-Erstellung
int sockfd = socket(domain, type, protocol)>
- sockfd: Socket-Deskriptor, eine Ganzzahl (wie ein Dateihandle) domain: Integer, gibt die Kommunikationsdomäne an. Wir verwenden AF_LOCAL wie im POSIX-Standard definiert für die Kommunikation zwischen Prozessen auf demselben Host. Für die Kommunikation zwischen Prozessen auf verschiedenen Hosts, die über IPV4 verbunden sind, verwenden wir AF_INET und AF_I NET 6 für Prozesse, die über IPV6 verbunden sind. Typ: Kommunikationstyp
SOCK_STREAM: TCP (zuverlässig, verbindungsorientiert)
SOCK_DGRAM: UDP-Protokoll (unzuverlässig, verbindungslos): Protokollwert für Internet Protocol (IP), der 0 ist. Dies ist dieselbe Zahl, die im Protokollfeld im IP-Header eines Pakets angezeigt wird. (Man Protocols für weitere Details)
2. Setsockopt
Dies hilft bei der Manipulation von Optionen für den Socket, auf den der Dateideskriptor sockfd verweist. Dies ist völlig optional, hilft aber bei der Wiederverwendung von Adresse und Port. Verhindert Fehler wie: Adresse wird bereits verwendet.
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);>
3. Binden
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);>
Nach der Erstellung des Sockets bindet die Bindefunktion den Socket an die in addr (benutzerdefinierte Datenstruktur) angegebene Adresse und Portnummer. Im Beispielcode binden wir den Server an den lokalen Host und verwenden daher INADDR_ANY, um die IP-Adresse anzugeben.
4. Hören Sie zu
int listen(int sockfd, int backlog);>
Es versetzt den Server-Socket in einen passiven Modus, in dem er darauf wartet, dass der Client sich dem Server nähert, um eine Verbindung herzustellen. Der Rückstand definiert die maximale Länge, auf die die Warteschlange ausstehender Verbindungen für sockfd anwachsen darf. Wenn eine Verbindungsanforderung eintrifft, während die Warteschlange voll ist, erhält der Client möglicherweise eine Fehlermeldung mit der Angabe ECONNREFUSED.
5. Akzeptieren
int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);>
Es extrahiert die erste Verbindungsanforderung aus der Warteschlange ausstehender Verbindungen für den Listening-Socket sockfd, erstellt einen neuen verbundenen Socket und gibt einen neuen Dateideskriptor zurück, der auf diesen Socket verweist. Zu diesem Zeitpunkt ist die Verbindung zwischen Client und Server hergestellt und sie sind bereit für die Datenübertragung.
Bühnen für den Kunden
1. Buchsenanschluss: Genau das Gleiche wie bei der Socket-Erstellung des Servers
2. Verbinden: Der Systemaufruf connect() verbindet den Socket, auf den der Dateideskriptor sockfd verweist, mit der durch addr angegebenen Adresse. Die Adresse und der Port des Servers werden in addr angegeben.
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);>
Implementierung
Hier tauschen wir eine Hallo-Nachricht zwischen Server und Client aus, um das Client/Server-Modell zu demonstrieren.
C-Programm zum Erstellen eines Servers
Server.c
C
// Server side C program to demonstrate Socket> // programming> #include> #include> #include> #include> #include> #include> #define PORT 8080> int> main(> int> argc,> char> const> * argv[])> {> > int> server_fd, new_socket;> > ssize_t valread;> > struct> sockaddr_in address;> > int> opt = 1;> > socklen_t addrlen => sizeof> (address);> > char> buffer[1024] = { 0 };> > char> * hello => 'Hello from server'> ;> > // Creating socket file descriptor> > if> ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) <0) {> > perror> (> 'socket failed'> );> > exit> (EXIT_FAILURE);> > }> > // Forcefully attaching socket to the port 8080> > if> (setsockopt(server_fd, SOL_SOCKET,> > SO_REUSEADDR | SO_REUSEPORT, &opt,> > sizeof> (opt))) {> > perror> (> 'setsockopt'> );> > exit> (EXIT_FAILURE);> > }> > address.sin_family = AF_INET;> > address.sin_addr.s_addr = INADDR_ANY;> > address.sin_port = htons(PORT);> > // Forcefully attaching socket to the port 8080> > if> (bind(server_fd, (> struct> sockaddr*)&address,> > sizeof> (address))> > <0) {> > perror> (> 'bind failed'> );> > exit> (EXIT_FAILURE);> > }> > if> (listen(server_fd, 3) <0) {> > perror> (> 'listen'> );> > exit> (EXIT_FAILURE);> > }> > if> ((new_socket> > = accept(server_fd, (> struct> sockaddr*)&address,> > &addrlen))> > <0) {> > perror> (> 'accept'> );> > exit> (EXIT_FAILURE);> > }> > valread = read(new_socket, buffer,> > 1024 - 1);> // subtract 1 for the null> > // terminator at the end> > printf> (> '%s
'> , buffer);> > send(new_socket, hello,> strlen> (hello), 0);> > printf> (> 'Hello message sent
'> );> > // closing the connected socket> > close(new_socket);> > // closing the listening socket> > close(server_fd);> > return> 0;> }> |
>
>
C-Programm zum Erstellen eines Clients
client.c
Nummerieren Sie das Alphabet
C
// Client side C program to demonstrate Socket> // programming> #include> #include> #include> #include> #include> #define PORT 8080> int> main(> int> argc,> char> const> * argv[])> {> > int> status, valread, client_fd;> > struct> sockaddr_in serv_addr;> > char> * hello => 'Hello from client'> ;> > char> buffer[1024] = { 0 };> > if> ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) <0) {> > printf> (> '
Socket creation error
'> );> > return> -1;> > }> > serv_addr.sin_family = AF_INET;> > serv_addr.sin_port = htons(PORT);> > // Convert IPv4 and IPv6 addresses from text to binary> > // form> > if> (inet_pton(AF_INET,> '127.0.0.1'> , &serv_addr.sin_addr)> > <= 0) {> > printf> (> > '
Invalid address/ Address not supported
'> );> > return> -1;> > }> > if> ((status> > = connect(client_fd, (> struct> sockaddr*)&serv_addr,> > sizeof> (serv_addr)))> > <0) {> > printf> (> '
Connection Failed
'> );> > return> -1;> > }> > send(client_fd, hello,> strlen> (hello), 0);> > printf> (> 'Hello message sent
'> );> > valread = read(client_fd, buffer,> > 1024 - 1);> // subtract 1 for the null> > // terminator at the end> > printf> (> '%s
'> , buffer);> > // closing the connected socket> > close(client_fd);> > return> 0;> }> |
Java-Typkonvertierung und -Casting
>
>
Ausgabe
Client:Hello message sent Hello from server Server:Hello from client Hello message sent>
Kompilieren
gcc client.c -o client gcc server.c -o server>
Weiter: Socket-Programmierung in C/C++: Umgang mit mehreren Clients auf dem Server ohne Multithreading