Prises Berkeley - Berkeley sockets

Berkeley sockets est une interface de programmation d'applications (API) pour les sockets Internet et les sockets de domaine Unix , utilisée pour la communication inter-processus (IPC). Il est généralement implémenté sous la forme d'une bibliothèque de modules pouvant être liés. Il a pour origine le système d' exploitation 4.2BSD Unix , sorti en 1983.

Une socket est une représentation abstraite ( handle ) du point de terminaison local d'un chemin de communication réseau. L'API des sockets Berkeley le représente comme un descripteur de fichier ( file handle ) dans la philosophie Unix qui fournit une interface commune pour l'entrée et la sortie des flux de données.

Les sockets Berkeley ont évolué avec peu de modifications d'un standard de facto à un composant de la spécification POSIX . Le terme sockets POSIX est essentiellement synonyme de sockets Berkeley , mais ils sont également connus sous le nom de sockets BSD , reconnaissant la première implémentation dans la distribution logicielle de Berkeley .

Historique et implémentations

Les sockets Berkeley sont originaires du système d' exploitation 4.2BSD Unix , sorti en 1983, en tant qu'interface de programmation. Ce n'est qu'en 1989, cependant, que l' Université de Californie à Berkeley a pu publier des versions du système d'exploitation et de la bibliothèque réseau exemptes des contraintes de licence d' Unix propriétaire d' AT&T Corporation .

Tous les systèmes d'exploitation modernes implémentent une version de l'interface socket Berkeley. Il est devenu l'interface standard pour les applications s'exécutant sur Internet . Même l' implémentation Winsock pour MS Windows, créée par des développeurs non affiliés, suit de près la norme.

L'API de BSD est écrit dans le langage de programmation C . La plupart des autres langages de programmation fournissent des interfaces similaires, généralement écrites sous la forme d'une bibliothèque wrapper basée sur l'API C.

Prises BSD et POSIX

Au fur et à mesure que l'API de socket Berkeley a évolué et a finalement abouti à l'API de socket POSIX, certaines fonctions ont été dépréciées ou supprimées et remplacées par d'autres. L'API POSIX est également conçue pour être réentrante .

action BSD POSIX
Conversion de l'adresse textuelle en adresse emballée inet_aton inet_pton
Conversion d'adresse emballée en adresse texte inet_ntoa inet_ntop
Recherche directe de nom d'hôte/service gethostbyname, gethostbyaddr, getservbyname, getservbyport getaddrinfo
Recherche inversée de nom d'hôte/service gethostbyaddr, getservbyport obtenirnominfo

Alternatives

Les COURANTS -Basé Interface Transport Layer API (TLI) offre une alternative à l'API socket. De nombreux systèmes qui fournissent l'API TLI fournissent également l'API de socket Berkeley.

Les systèmes non Unix exposent souvent l'API de socket Berkeley avec une couche de traduction vers une API de mise en réseau native. Plan 9 et Genode utilisent des API de système de fichiers avec des fichiers de contrôle plutôt que des descripteurs de fichiers.

Fichiers d'en-tête

L'interface de socket Berkeley est définie dans plusieurs fichiers d'en-tête. Les noms et le contenu de ces fichiers diffèrent légèrement entre les implémentations. En général, ils comprennent :

Déposer La description
sys/socket.h Fonctions de socket de base et structures de données.
netinet/in.h Les familles d'adresses AF_INET et AF_INET6 et leurs familles de protocoles correspondantes, PF_INET et PF_INET6. Ceux-ci incluent les adresses IP standard et les numéros de port TCP et UDP.
sys/un.h Famille d'adresses PF_UNIX et PF_LOCAL. Utilisé pour la communication locale entre les programmes exécutés sur le même ordinateur.
arpa/inet.h Fonctions de manipulation des adresses IP numériques.
netdb.h Fonctions de traduction des noms de protocole et des noms d'hôte en adresses numériques. Recherche des données locales ainsi que des services de noms.

Fonctions de l'API de socket

Organigramme de la transaction client-serveur à l'aide de sockets avec le protocole de contrôle de transmission (TCP).

L'API de socket Berkeley fournit généralement les fonctions suivantes :

  • socket() crée une nouvelle socket d'un certain type, identifiée par un nombre entier, et lui alloue des ressources système.
  • bind() est généralement utilisé côté serveur et associe une socket à une structure d'adresse de socket, c'est-à-dire une adresse IP locale spécifiée et un numéro de port.
  • listen() est utilisé côté serveur et fait passer un socket TCP lié à l'état d'écoute.
  • connect() est utilisé côté client et attribue un numéro de port local libre à une socket. Dans le cas d'un socket TCP, cela provoque une tentative d'établissement d'une nouvelle connexion TCP.
  • accept() est utilisé côté serveur. Il accepte une tentative entrante reçue de créer une nouvelle connexion TCP à partir du client distant et crée un nouveau socket associé à la paire d'adresses de socket de cette connexion.
  • send() , recv() , sendto() et recvfrom() sont utilisés pour envoyer et recevoir des données. Les fonctions standard write() et read() peuvent également être utilisées.
  • close() oblige le système à libérer les ressources allouées à un socket. En cas de TCP, la connexion est interrompue.
  • gethostbyname() et gethostbyaddr() sont utilisés pour résoudre les noms et adresses d'hôtes. IPv4 uniquement.
  • select() est utilisé pour suspendre, en attendant qu'un ou plusieurs sockets d'une liste fournie de sockets soient prêts à lire, prêts à écrire, ou qui ont des erreurs.
  • poll() est utilisé pour vérifier l'état d'une socket dans un ensemble de sockets. L'ensemble peut être testé pour voir si une socket peut être écrite, lue depuis ou si une erreur s'est produite.
  • getsockopt() est utilisé pour récupérer la valeur actuelle d'une option de socket particulière pour le socket spécifié.
  • setsockopt() est utilisé pour définir une option de socket particulière pour le socket spécifié.

prise

La fonction socket() crée un point de terminaison pour la communication et renvoie un descripteur de fichier pour la socket. Il utilise trois arguments :

  • domain , qui spécifie la famille de protocoles de la socket créée. Par exemple:
    • AF_INET pour le protocole réseau IPv4 (IPv4 uniquement)
    • AF_INET6 pour IPv6 (et dans certains cas, rétrocompatible avec IPv4)
    • AF_UNIX pour le socket local (en utilisant un nœud de système de fichiers spécial)
  • type , l'un des suivants :
    • SOCK_STREAM (service fiable orienté flux ou Stream Sockets )
    • SOCK_DGRAM (service de datagramme ou sockets de datagramme )
    • SOCK_SEQPACKET (service de paquets séquencés fiable)
    • SOCK_RAW (protocoles bruts au sommet de la couche réseau)
  • protocole spécifiant le protocole de transport réel à utiliser. Les plus courants sont IPPROTO_TCP , IPPROTO_SCTP , IPPROTO_UDP , IPPROTO_DCCP . Ces protocoles sont spécifiés dans le fichier netinet/in.h . La valeur 0 peut être utilisée pour sélectionner un protocole par défaut à partir du domaine et du type sélectionnés.

La fonction renvoie -1 si une erreur s'est produite. Sinon, il renvoie un entier représentant le descripteur nouvellement affecté.

lier

bind() associe une socket à une adresse. Lorsqu'un socket est créé avec socket() , il ne reçoit qu'une famille de protocoles, mais pas d'adresse. Cette association doit être effectuée avant que le socket ne puisse accepter les connexions d'autres hôtes. La fonction a trois arguments :

  • sockfd , un descripteur représentant la socket
  • my_addr , un pointeur vers une structure sockaddr représentant l'adresse à laquelle se lier.
  • addrlen , un champ de type socklen_t spécifiant la taille de la structure sockaddr .

bind() renvoie 0 en cas de succès et -1 en cas d'erreur.

Ecoutez

Une fois qu'un socket a été associé à une adresse, listen() le prépare pour les connexions entrantes. Cependant, cela n'est nécessaire que pour les modes de données orientés flux (orientés connexion), c'est-à-dire pour les types de socket ( SOCK_STREAM , SOCK_SEQPACKET ). listen() requiert deux arguments :

  • sockfd , un descripteur de socket valide.
  • backlog , un entier représentant le nombre de connexions en attente qui peuvent être mises en file d'attente à tout moment. Le système d'exploitation place généralement un plafond sur cette valeur.

Une fois qu'une connexion est acceptée, elle est retirée de la file d'attente. En cas de succès, 0 est renvoyé. Si une erreur se produit, -1 est renvoyé.

J'accepte

Lorsqu'une application est à l'écoute de connexions orientées flux provenant d'autres hôtes, elle est notifiée de tels événements (cf. fonction select() ) et doit initialiser la connexion à l'aide de la fonction accept() . Il crée un nouveau socket pour chaque connexion et supprime la connexion de la file d'attente d'écoute. La fonction a les arguments suivants :

  • sockfd , le descripteur du socket d'écoute qui a la connexion en file d'attente.
  • cliaddr , un pointeur vers une structure sockaddr pour recevoir les informations d'adresse du client.
  • addrlen , un pointeur vers un emplacement socklen_t qui spécifie la taille de la structure d'adresse client transmise à accept(). Lorsque accept() revient, cet emplacement contient la taille (en octets) de la structure.

accept() renvoie le nouveau descripteur de socket pour la connexion acceptée, ou la valeur -1 si une erreur se produit. Toutes les autres communications avec l'hôte distant s'effectuent désormais via ce nouveau socket.

Les sockets de datagramme ne nécessitent pas de traitement par accept() puisque le récepteur peut répondre immédiatement à la requête en utilisant le socket d'écoute.

relier

connect() établit un lien de communication direct avec un hôte distant spécifique identifié par son adresse via une socket, identifiée par son descripteur de fichier.

Lors de l'utilisation d'un protocole orienté connexion, cela établit une connexion. Certains types de protocoles sont sans connexion, notamment le User Datagram Protocol . Lorsqu'il est utilisé avec des protocoles sans connexion, connect définit l'adresse distante pour l'envoi et la réception de données, permettant l'utilisation de fonctions telles que send et recv . Dans ces cas, la fonction de connexion empêche la réception de datagrammes provenant d'autres sources.

connect() renvoie un entier représentant le code d'erreur : 0 représente le succès, tandis que –1 représente une erreur. Historiquement, dans les systèmes dérivés de BSD, l'état d'un descripteur de socket n'est pas défini si l'appel pour se connecter échoue (comme cela est spécifié dans la spécification Single Unix), ainsi, les applications portables devraient fermer le descripteur de socket immédiatement et obtenir un nouveau descripteur avec socket(), en cas d'échec de l'appel à connect().

gethostbyname et gethostbyaddr

Les fonctions gethostbyname() et gethostbyaddr() sont utilisées pour résoudre les noms et adresses d'hôtes dans le système de noms de domaine ou les autres mécanismes de résolution de l'hôte local (par exemple, /etc/hosts lookup). Ils renvoient un pointeur vers un objet de type struct hostent , qui décrit un hôte de protocole Internet . Les fonctions utilisent les arguments suivants :

  • name spécifie le nom DNS de l'hôte.
  • addr spécifie un pointeur vers une structure in_addr contenant l'adresse de l'hôte.
  • len spécifie la longueur, en octets, de addr .
  • type spécifie le type de famille d'adresses (par exemple, AF_INET) de l'adresse hôte.

Les fonctions renvoient un pointeur NULL en cas d'erreur, auquel cas l'entier externe h_errno peut être vérifié pour voir s'il s'agit d'un échec temporaire ou d'un hôte invalide ou inconnu. Sinon, une structure valide hostent * est renvoyée.

Ces fonctions ne sont pas strictement un composant de l'API socket BSD, mais sont souvent utilisées en conjonction avec les fonctions API. De plus, ces fonctions sont désormais considérées comme des interfaces héritées pour interroger le système de noms de domaine. De nouvelles fonctions totalement indépendantes du protocole (supportant IPv6) ont été définies. Ces nouvelles fonctions sont getaddrinfo() et getnameinfo() , et sont basées sur une nouvelle structure de données addrinfo .

Protocole et adresse aux familles

L'API de socket Berkeley est une interface générale pour la mise en réseau et la communication interprocessus, et prend en charge l'utilisation de divers protocoles réseau et architectures d'adresses.

Ce qui suit répertorie un échantillon de familles de protocoles (précédées de l'identifiant symbolique standard) définies dans une implémentation Linux ou BSD moderne :

Identifiant Fonction ou utilisation
PF_LOCAL, PF_UNIX, PF_FILE Local à héberger (pipes et domaine de fichier)
PF_INET Protocole Internet version 4
PF_AX25 Radioamateur AX.25
PF_IPX L' échange de paquets inter-réseaux de Novell
PF_APPLETALK AppleTalk
PF_NETROM Radioamateur NetROM (lié à AX.25)
PF_PONT Pont multiprotocole
PF_ATMPVC Circuits virtuels permanents en mode de transfert asynchrone
PF_ATMSVC Circuits virtuels commutés en mode de transfert asynchrone
PF_INET6 Protocole Internet version 6
PF_DECnet Réservé au projet DECnet
PF_NETBEUI Réservé au projet 802.2LLC
PF_SÉCURITÉ Pseudo AF de rappel de sécurité
PF_KEY API de gestion de clés PF_KEY
PF_NETLINK, PF_ROUTE API de routage
PF_PAQUET Prises de capture de paquets
PF_ECONET Acorn Econet
PF_SNA Projet d' architecture de réseau de systèmes Linux (SNA)
PF_IRDA Prises IrDA
PF_PPPOX PPP sur X sockets
PF_WANPIPE Prises API Sangoma Wanpipe
PF_BLUETOOTH Prises Bluetooth

Une socket pour les communications est créée avec la socket()fonction, en spécifiant la famille de protocoles souhaitée ( PF_ -identifier ) comme argument.

Le concept de conception original de l'interface socket faisait la distinction entre les types de protocole (familles) et les types d'adresses spécifiques que chacun peut utiliser. Il a été envisagé qu'une famille de protocoles puisse avoir plusieurs types d'adresses. Les types d'adresses étaient définis par des constantes symboliques supplémentaires, en utilisant le préfixe AF au lieu de PF . Les identificateurs AF sont destinés à toutes les structures de données qui traitent spécifiquement du type d'adresse et non de la famille de protocoles. Cependant, ce concept de séparation du protocole et du type d'adresse n'a pas trouvé de support d'implémentation et les constantes AF ont été définies par l'identifiant de protocole correspondant, laissant la distinction entre les constantes AF et PF comme un argument technique sans conséquence pratique. En effet, il existe une grande confusion dans l'utilisation appropriée des deux formes.

La spécification POSIX.1—2008 ne spécifie aucune constante PF , mais uniquement des constantes AF

Prises brutes

Les sockets bruts fournissent une interface simple qui contourne le traitement par la pile TCP/IP de l'hôte. Ils permettent la mise en œuvre de protocoles de mise en réseau dans l'espace utilisateur et aident au débogage de la pile de protocoles. Les sockets bruts sont utilisés par certains services, tels que ICMP , qui fonctionnent au niveau de la couche Internet du modèle TCP/IP.

Mode bloquant et non bloquant

Les prises Berkeley peuvent fonctionner dans l'un des deux modes suivants : bloquant ou non bloquant.

Une socket bloquante ne rend pas le contrôle tant qu'elle n'a pas envoyé (ou reçu) certaines ou toutes les données spécifiées pour l'opération. Il est normal qu'un socket bloquant n'envoie pas toutes les données. L'application doit vérifier la valeur de retour pour déterminer combien d'octets ont été envoyés ou reçus et elle doit renvoyer toutes les données non déjà traitées. Lors de l'utilisation de sockets bloquants, une attention particulière doit être accordée à accept() car il peut toujours bloquer après avoir indiqué la lisibilité si un client se déconnecte pendant la phase de connexion.

Un socket non bloquant renvoie tout ce qui se trouve dans le tampon de réception et continue immédiatement. S'ils ne sont pas écrits correctement, les programmes utilisant des sockets non bloquants sont particulièrement sensibles aux conditions de concurrence en raison des variations de vitesse de liaison réseau.

Une socket est généralement définie en mode bloquant ou non bloquant à l'aide des fonctions fcntl et ioctl .

Prises de terminaison

Le système d'exploitation ne libère pas les ressources allouées à un socket tant que le socket n'est pas fermé. Ceci est particulièrement important si l' appel de connexion échoue et sera réessayé.

Lorsqu'une application ferme un socket, seule l'interface avec le socket est détruite. Il est de la responsabilité du noyau de détruire le socket en interne. Parfois, un socket peut entrer dans un état TIME_WAIT , côté serveur, jusqu'à 4 minutes.

Sur les systèmes SVR4 , l'utilisation de close()peut supprimer des données. L'utilisation de shutdown()ou de SO_LINGER peut être requise sur ces systèmes pour garantir la livraison de toutes les données.

Exemple client-serveur utilisant TCP

Le protocole TCP ( Transmission Control Protocol ) est un protocole orienté connexion qui fournit une variété de fonctions de correction d'erreurs et de performances pour la transmission de flux d'octets. Un processus crée un socket TCP en appelant la socket()fonction avec les paramètres de la famille de protocoles ( PF INET , PF_INET6 ), le mode de socket pour les sockets de flux ( SOCK_STREAM ) et l'identifiant de protocole IP pour TCP ( IPPROTO_TCP ).

Serveur

L'établissement d'un serveur TCP implique les étapes de base suivantes :

  • Création d'un socket TCP avec un appel à socket().
  • Lier le socket au port d'écoute ( bind() ) après avoir défini le numéro de port.
  • Préparation de la socket à écouter les connexions (en faisant une socket d'écoute), avec un appel à listen() .
  • Accepter les connexions entrantes ( accept() ). Cela bloque le processus jusqu'à ce qu'une connexion entrante soit reçue et renvoie un descripteur de socket pour la connexion acceptée. Le descripteur initial reste un descripteur d'écoute, et accept() peut être appelé à nouveau à tout moment avec cette socket, jusqu'à sa fermeture.
  • Communiquer avec l'hôte distant avec les fonctions API send() et recv() , ainsi qu'avec les fonctions générales write() et read() .
  • Fermeture de chaque socket qui a été ouverte après utilisation avec la fonction close()

Le programme suivant crée un serveur TCP à l'écoute sur le port numéro 1100 :

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  
  int main(void)
  {
    struct sockaddr_in sa;
    int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (SocketFD == -1) {
      perror("cannot create socket");
      exit(EXIT_FAILURE);
    }
  
    memset(&sa, 0, sizeof sa);
  
    sa.sin_family = AF_INET;
    sa.sin_port = htons(1100);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
  
    if (bind(SocketFD,(struct sockaddr *)&sa, sizeof sa) == -1) {
      perror("bind failed");
      close(SocketFD);
      exit(EXIT_FAILURE);
    }
  
    if (listen(SocketFD, 10) == -1) {
      perror("listen failed");
      close(SocketFD);
      exit(EXIT_FAILURE);
    }
  
    for (;;) {
      int ConnectFD = accept(SocketFD, NULL, NULL);
  
      if (ConnectFD == -1) {
        perror("accept failed");
        close(SocketFD);
        exit(EXIT_FAILURE);
      }
  
      /* perform read write operations ... 
      read(ConnectFD, buff, size)
      */
  
      if (shutdown(ConnectFD, SHUT_RDWR) == -1) {
        perror("shutdown failed");
        close(ConnectFD);
        close(SocketFD);
        exit(EXIT_FAILURE);
      }
      close(ConnectFD);
    }

    close(SocketFD);
    return EXIT_SUCCESS;  
}

Client

La programmation d'une application client TCP implique les étapes suivantes :

  • Création d'un socket TCP.
  • Connexion au serveur ( connect () ), en faisant passer une sockaddr_instructure à l' sin_familyensemble à AF_INET , sin_portensemble au port du noeud final est à l' écoute (dans l' ordre des octets du réseau), et sin_addrréglée sur l'adresse IP du serveur d'écoute (également en octets du réseau ordre).
  • Communiquer avec l'hôte distant avec les fonctions API send() et recv() , ainsi qu'avec les fonctions générales write() et read() .
  • Fermeture de chaque socket qui a été ouverte après utilisation avec la fonction close().
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  
  int main(void)
  {
    struct sockaddr_in sa;
    int res;
    int SocketFD;

    SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (SocketFD == -1) {
      perror("cannot create socket");
      exit(EXIT_FAILURE);
    }
  
    memset(&sa, 0, sizeof sa);
  
    sa.sin_family = AF_INET;
    sa.sin_port = htons(1100);
    res = inet_pton(AF_INET, "192.168.1.3", &sa.sin_addr);

    if (connect(SocketFD, (struct sockaddr *)&sa, sizeof sa) == -1) {
      perror("connect failed");
      close(SocketFD);
      exit(EXIT_FAILURE);
    }
  
    /* perform read write operations ... */
  
    close(SocketFD);
    return EXIT_SUCCESS;
  }

Exemple client-serveur utilisant UDP

Le protocole UDP ( User Datagram Protocol ) est un protocole sans connexion sans garantie de livraison. Les paquets UDP peuvent arriver dans le désordre, plusieurs fois ou pas du tout. En raison de cette conception minimale, UDP a considérablement moins de temps système que TCP. Être sans connexion signifie qu'il n'y a pas de concept de flux ou de connexion permanente entre deux hôtes. Ces données sont appelées datagrammes ( Datagram Sockets ).

L'espace d'adressage UDP, l'espace des numéros de port UDP (dans la terminologie ISO, les TSAP ), est complètement disjoint de celui des ports TCP.

Serveur

Une application peut configurer un serveur UDP sur le numéro de port 7654 comme suit. Les programmes contiennent une boucle infinie qui reçoit des datagrammes UDP avec la fonction recvfrom() .

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h> /* for close() for socket */ 
#include <stdlib.h>

int main(void)
{
  int sock;
  struct sockaddr_in sa; 
  char buffer[1024];
  ssize_t recsize;
  socklen_t fromlen;

  memset(&sa, 0, sizeof sa);
  sa.sin_family = AF_INET;
  sa.sin_addr.s_addr = htonl(INADDR_ANY);
  sa.sin_port = htons(7654);
  fromlen = sizeof sa;

  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (bind(sock, (struct sockaddr *)&sa, sizeof sa) == -1) {
    perror("error bind failed");
    close(sock);
    exit(EXIT_FAILURE);
  }

  for (;;) {
    recsize = recvfrom(sock, (void*)buffer, sizeof buffer, 0, (struct sockaddr*)&sa, &fromlen);
    if (recsize < 0) {
      fprintf(stderr, "%s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }
    printf("recsize: %d\n ", (int)recsize);
    sleep(1);
    printf("datagram: %.*s\n", (int)recsize, buffer);
  }
}

Client

Ce qui suit est un programme client pour envoyer un paquet UDP contenant la chaîne "Hello World!" à l'adresse 127.0.0.1 au numéro de port 7654.

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>

int main(void)
{
  int sock;
  struct sockaddr_in sa;
  int bytes_sent;
  char buffer[200];
 
  strcpy(buffer, "hello world!");
 
  /* create an Internet, datagram, socket using UDP */
  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (sock == -1) {
      /* if socket failed to initialize, exit */
      printf("Error Creating Socket");
      exit(EXIT_FAILURE);
  }
 
  /* Zero out socket address */
  memset(&sa, 0, sizeof sa);
  
  /* The address is IPv4 */
  sa.sin_family = AF_INET;
 
   /* IPv4 addresses is a uint32_t, convert a string representation of the octets to the appropriate value */
  sa.sin_addr.s_addr = inet_addr("127.0.0.1");
  
  /* sockets are unsigned shorts, htons(x) ensures x is in network byte order, set the port to 7654 */
  sa.sin_port = htons(7654);
 
  bytes_sent = sendto(sock, buffer, strlen(buffer), 0,(struct sockaddr*)&sa, sizeof sa);
  if (bytes_sent < 0) {
    printf("Error sending packet: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }
 
  close(sock); /* close the socket */
  return 0;
}

Dans ce code, buffer est un pointeur vers les données à envoyer et buffer_length spécifie la taille des données.

Les références

La définition standard de jure de l'interface Sockets est contenue dans la norme POSIX, connue sous le nom de :

  • Norme IEEE . 1003.1-2001 Norme pour les technologies de l'information—Interface de système d'exploitation portable (POSIX).
  • Norme technique du groupe ouvert : spécifications de base, numéro 6, décembre 2001.
  • ISO/CEI 9945:2002

Des informations sur cette norme et les travaux en cours sur celle-ci sont disponibles sur le site Web d'Austin .

Les extensions IPv6 de l'API de socket de base sont documentées dans les RFC 3493 et ​​RFC 3542.

Liens externes