Unix Socket - Kernfunktionen

In diesem Kapitel werden die wichtigsten Socket-Funktionen beschrieben, die zum Schreiben eines vollständigen TCP-Clients und -Servers erforderlich sind.

Das folgende Diagramm zeigt die vollständige Client- und Server-Interaktion -

Die Socket-Funktion

Um eine Netzwerk-E / A durchzuführen, muss ein Prozess zunächst die Socket-Funktion aufrufen und den Typ des gewünschten Kommunikationsprotokolls und die Protokollfamilie usw. angeben.

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

int socket (int family, int type, int protocol);

Dieser Aufruf gibt einen Socket-Deskriptor zurück, den Sie in späteren Systemaufrufen verwenden können, oder -1 bei einem Fehler.

Parameter

family - Es gibt die Protokollfamilie an und ist eine der unten gezeigten Konstanten. -

Familie Beschreibung
AF_INET IPv4-Protokolle
AF_INET6 IPv6-Protokolle
AF_LOCAL Unix-Domänenprotokolle
AF_ROUTE Routing-Sockets
AF_KEY Ket Steckdose

Dieses Kapitel behandelt keine anderen Protokolle als IPv4.

type- Es gibt die Art der gewünschten Steckdose an. Es kann einen der folgenden Werte annehmen -

Art Beschreibung
SOCK_STREAM Stream-Socket
SOCK_DGRAM Datagramm-Socket
SOCK_SEQPACKET Sequenzierter Paketsocket
SOCK_RAW Roher Sockel

protocol - Das Argument sollte auf den unten angegebenen Protokolltyp oder auf 0 gesetzt werden, um den Standard des Systems für die angegebene Kombination aus Familie und Typ auszuwählen. -

Protokoll Beschreibung
IPPROTO_TCP TCP-Transportprotokoll
IPPROTO_UDP UDP-Transportprotokoll
IPPROTO_SCTP SCTP-Transportprotokoll

Die Connect - Funktion

Die Verbindungsfunktion wird von einem TCP-Client verwendet, um eine Verbindung mit einem TCP-Server herzustellen.

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

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Dieser Aufruf gibt 0 zurück, wenn eine erfolgreiche Verbindung zum Server hergestellt wurde, andernfalls wird bei einem Fehler -1 zurückgegeben.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • serv_addr - Es ist ein Zeiger auf struct sockaddr, der die Ziel-IP-Adresse und den Port enthält.

  • addrlen - Stellen Sie es auf sizeof (struct sockaddr) ein.

Die bind - Funktion

Die Bindefunktion weist einem Socket eine lokale Protokolladresse zu. Bei den Internetprotokollen ist die Protokolladresse die Kombination aus einer 32-Bit-IPv4-Adresse oder einer 128-Bit-IPv6-Adresse sowie einer 16-Bit-TCP- oder UDP-Portnummer. Diese Funktion wird nur vom TCP-Server aufgerufen.

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

int bind(int sockfd, struct sockaddr *my_addr,int addrlen);

Dieser Aufruf gibt 0 zurück, wenn er erfolgreich an die Adresse gebunden wurde, andernfalls wird bei einem Fehler -1 zurückgegeben.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • my_addr - Es ist ein Zeiger auf struct sockaddr, der die lokale IP-Adresse und den Port enthält.

  • addrlen - Stellen Sie es auf sizeof (struct sockaddr) ein.

Sie können Ihre IP-Adresse und Ihren Port automatisch eingeben

Ein 0-Wert für die Portnummer bedeutet, dass das System einen zufälligen Port auswählt , und ein INADDR_ANY- Wert für die IP-Adresse bedeutet, dass die IP-Adresse des Servers automatisch zugewiesen wird.

server.sin_port = 0;  		     
server.sin_addr.s_addr = INADDR_ANY;

NOTE- Alle Ports unter 1024 sind reserviert. Sie können einen Port über 1024 und unter 65535 festlegen, es sei denn, diese werden von anderen Programmen verwendet.

Die Listen- Funktion

Die Listen- Funktion wird nur von einem TCP-Server aufgerufen und führt zwei Aktionen aus:

  • Die Listen-Funktion konvertiert einen nicht verbundenen Socket in einen passiven Socket und gibt an, dass der Kernel eingehende Verbindungsanforderungen akzeptieren soll, die an diesen Socket gerichtet sind.

  • Das zweite Argument für diese Funktion gibt die maximale Anzahl von Verbindungen an, die der Kernel für diesen Socket in die Warteschlange stellen soll.

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

int listen(int sockfd,int backlog);

Dieser Aufruf gibt bei Erfolg 0 zurück, andernfalls gibt er bei Fehler -1 zurück.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • backlog - Dies ist die Anzahl der zulässigen Verbindungen.

Die akzeptieren Funktion

Die Akzeptanzfunktion wird von einem TCP-Server aufgerufen, um die nächste abgeschlossene Verbindung von der Vorderseite der Warteschlange für abgeschlossene Verbindungen zurückzugeben. Die Signatur des Anrufs lautet wie folgt:

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

int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

Dieser Aufruf gibt bei Erfolg einen nicht negativen Deskriptor zurück, andernfalls wird bei einem Fehler -1 zurückgegeben. Es wird angenommen, dass der zurückgegebene Deskriptor ein Client-Socket-Deskriptor ist, und alle Lese- / Schreibvorgänge werden an diesem Deskriptor ausgeführt, um mit dem Client zu kommunizieren.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • cliaddr - Es ist ein Zeiger auf struct sockaddr, der die Client-IP-Adresse und den Port enthält.

  • addrlen - Stellen Sie es auf sizeof (struct sockaddr) ein.

Die Sendefunktion

Die Sendefunktion wird verwendet , um Daten über Stream - Sockets oder CONNECTED Datagramm - Sockets zu senden. Wenn Sie Daten über UNCONNECTED-Datagramm-Sockets senden möchten, müssen Sie die Funktion sendto () verwenden.

Sie können den Systemaufruf write () verwenden, um Daten zu senden. Die Unterschrift lautet wie folgt:

int send(int sockfd, const void *msg, int len, int flags);

Dieser Aufruf gibt die Anzahl der gesendeten Bytes zurück, andernfalls wird bei einem Fehler -1 zurückgegeben.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • msg - Es ist ein Zeiger auf die Daten, die Sie senden möchten.

  • len - Dies ist die Länge der Daten, die Sie senden möchten (in Bytes).

  • flags - Es wird auf 0 gesetzt.

Die Recv- Funktion

Die Recv- Funktion wird verwendet, um Daten über Stream-Sockets oder CONNECTED-Datagramm-Sockets zu empfangen. Wenn Sie Daten über UNCONNECTED-Datagramm-Sockets empfangen möchten, müssen Sie recvfrom () verwenden.

Sie können den Systemaufruf read () verwenden, um die Daten zu lesen. Dieser Aufruf wird im Kapitel Hilfsfunktionen erläutert.

int recv(int sockfd, void *buf, int len, unsigned int flags);

Dieser Aufruf gibt die Anzahl der in den Puffer gelesenen Bytes zurück, andernfalls wird bei einem Fehler -1 zurückgegeben.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • buf - Es ist der Puffer, in den die Informationen eingelesen werden.

  • len - Dies ist die maximale Länge des Puffers.

  • flags - Es wird auf 0 gesetzt.

Die sendto- Funktion

Die Sendto- Funktion wird verwendet, um Daten über UNCONNECTED-Datagramm-Sockets zu senden. Die Unterschrift lautet wie folgt:

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

Dieser Aufruf gibt die Anzahl der gesendeten Bytes zurück, andernfalls wird bei einem Fehler -1 zurückgegeben.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • msg - Es ist ein Zeiger auf die Daten, die Sie senden möchten.

  • len - Dies ist die Länge der Daten, die Sie senden möchten (in Bytes).

  • flags - Es wird auf 0 gesetzt.

  • to - Es ist ein Zeiger auf struct sockaddr für den Host, an den Daten gesendet werden müssen.

  • tolen - Es wird auf sizeof (struct sockaddr) gesetzt.

Die Funktion recvfrom

Die Funktion recvfrom wird verwendet, um Daten von UNCONNECTED-Datagramm-Sockets zu empfangen.

int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);

Dieser Aufruf gibt die Anzahl der in den Puffer gelesenen Bytes zurück, andernfalls wird bei einem Fehler -1 zurückgegeben.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • buf - Es ist der Puffer, in den die Informationen eingelesen werden.

  • len - Dies ist die maximale Länge des Puffers.

  • flags - Es wird auf 0 gesetzt.

  • from - Es ist ein Zeiger auf struct sockaddr für den Host, auf dem Daten gelesen werden müssen.

  • fromlen - Es wird auf sizeof (struct sockaddr) gesetzt.

Die enge Funktion

Die Schließfunktion wird verwendet, um die Kommunikation zwischen dem Client und dem Server zu schließen. Die Syntax lautet wie folgt:

int close( int sockfd );

Dieser Aufruf gibt bei Erfolg 0 zurück, andernfalls gibt er bei Fehler -1 zurück.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

Die Shutdown - Funktion

Die Shutdown- Funktion wird verwendet, um die Kommunikation zwischen dem Client und dem Server ordnungsgemäß zu schließen. Diese Funktion bietet mehr Kontrolle im Vergleich zur Schließfunktion . Unten ist die Syntax des Herunterfahrens angegeben -

int shutdown(int sockfd, int how);

Dieser Aufruf gibt bei Erfolg 0 zurück, andernfalls gibt er bei Fehler -1 zurück.

Parameter

  • sockfd - Es ist ein Socket-Deskriptor, der von der Socket-Funktion zurückgegeben wird.

  • how - Geben Sie eine der Zahlen ein -

    • 0 - zeigt an, dass das Empfangen nicht erlaubt ist,

    • 1 - zeigt an, dass das Senden nicht erlaubt ist, und

    • 2- zeigt an, dass sowohl Senden als auch Empfangen nicht zulässig sind. Wenn how auf 2 gesetzt ist, ist es dasselbe wie close ().

Die select - Funktion

Die Auswahlfunktion gibt an, welcher der angegebenen Dateideskriptoren zum Lesen oder Schreiben bereit ist oder eine Fehlerbedingung aussteht.

Wenn eine Anwendung recv oder recvfrom aufruft , wird sie blockiert, bis Daten für diesen Socket eintreffen. Eine Anwendung kann eine andere nützliche Verarbeitung ausführen, während der eingehende Datenstrom leer ist. Eine andere Situation ist, wenn eine Anwendung Daten von mehreren Sockets empfängt.

Das Aufrufen von recv oder recvfrom an einem Socket, dessen Eingabewarteschlange keine Daten enthält, verhindert den sofortigen Empfang von Daten von anderen Sockets. Der Funktionsaufruf select löst dieses Problem, indem das Programm alle Socket-Handles abfragen kann, um festzustellen, ob sie für nicht blockierende Lese- und Schreibvorgänge verfügbar sind.

Unten ist die Syntax von select - angegeben.

int select(int  nfds, fd_set  *readfds, fd_set  *writefds, fd_set *errorfds, struct timeval *timeout);

Dieser Aufruf gibt bei Erfolg 0 zurück, andernfalls gibt er bei Fehler -1 zurück.

Parameter

  • nfds- Gibt den Bereich der zu testenden Dateideskriptoren an. Die Funktion select () testet Dateideskriptoren im Bereich von 0 bis nfds-1

  • readfds- Es zeigt auf ein Objekt vom Typ fd_set , das bei der Eingabe die zu lesenden Dateideskriptoren angibt und bei der Ausgabe angibt, welche Dateideskriptoren zum Lesen bereit sind. Es kann NULL sein, um eine leere Menge anzuzeigen.

  • writefds- Es zeigt auf ein Objekt vom Typ fd_set , das bei der Eingabe die zu beschreibenden Dateideskriptoren angibt und bei der Ausgabe angibt, welche Dateideskriptoren schreibbereit sind. Es kann NULL sein, um eine leere Menge anzuzeigen.

  • exceptfds- Es zeigt auf ein Objekt vom Typ fd_set , das bei der Eingabe die Dateideskriptoren angibt, die auf anstehende Fehlerbedingungen überprüft werden sollen, und bei der Ausgabe angibt, bei welchen Dateideskriptoren Fehlerbedingungen anstehen. Es kann NULL sein, um eine leere Menge anzuzeigen.

  • timeout- Es zeigt auf eine Zeitstruktur, die angibt, wie lange der Auswahlaufruf die Deskriptoren für eine verfügbare E / A-Operation abfragen soll. Wenn der Timeout-Wert 0 ist, wird select sofort zurückgegeben. Wenn das Timeout-Argument NULL ist, wird select blockiert, bis mindestens ein Datei- / Socket-Handle für eine verfügbare E / A-Operation bereit ist. Andernfalls wird select nach Ablauf der Zeitspanne im Timeout zurückgegeben ODER, wenn mindestens ein Datei- / Socket-Deskriptor für eine E / A-Operation bereit ist.

Der Rückgabewert von select ist die Anzahl der Handles, die in den Dateideskriptorsätzen angegeben sind, die für die E / A bereit sind. Wenn das im Timeout-Feld angegebene Zeitlimit erreicht ist, wählen Sie return 0 aus. Die folgenden Makros zum Bearbeiten eines Dateideskriptorsatzes sind vorhanden:

  • FD_CLR(fd, &fdset)- Löscht das Bit für den Dateideskriptor fd im Dateideskriptorsatz fdset.

  • FD_ISSET(fd, &fdset)- Gibt einen Wert ungleich Null zurück, wenn das Bit für den Dateideskriptor fd in dem Dateideskriptorsatz gesetzt ist, auf den fdset zeigt , andernfalls 0.

  • FD_SET(fd, &fdset) - Setzt das Bit für den Dateideskriptor fd im Dateideskriptorsatz fdset.

  • FD_ZERO(&fdset) - Initialisiert den Dateideskriptorsatz fdset so, dass er für alle Dateideskriptoren null Bit enthält.

Das Verhalten dieser Makros ist undefiniert, wenn das Argument fd kleiner als 0 oder größer oder gleich FD_SETSIZE ist.

Beispiel

fd_set fds;

struct timeval tv;

/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;

/* tv now represents 1.5 seconds */
FD_ZERO(&fds);

/* adds sock to the file descriptor set */
FD_SET(sock, &fds); 

/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);

if (FD_ISSET(sock, &fds)) {
   recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
   /* do something */
}
else {
   /* do something else */
}