Comprendre la structure msghdr à partir de sys / socket.h

J’essaie de comprendre les membres suivants de la structure msghdr de la lib sys / socket.h .

  • struct iovec *msg_iov scatter/gather array
  • void *msg_control ancillary data, see below

Il indique ci-dessous:

Les données auxiliaires consistent en une séquence de paires, chacune constituée d’une structure cmsghdr suivie d’un tableau de données. Le tableau de données contient le message de données auxiliaires et la structure cmsghdr contient des informations descriptives permettant à une application d’parsingr correctement les données.


Je suppose que la structure msghdr contient les informations d’en-tête de protocole? Si oui … *msg_iov est le “vecteur” d’entrée / sortie des parameters dans la requête / réponse? et le *msg_control contient les messages de réponse?

msg_iov est un tableau de tampons d’entrée / sortie de longueur msg_iovlen . Chaque membre de ce tableau contient un pointeur sur un tampon de données et la taille du tampon. C’est là que les données à lire / écrire vivent. Il vous permet de lire / écrire sur un tableau de tampons qui ne sont pas nécessairement dans des régions de mémoire contiguës.

msg_control pointe vers un tampon de taille msg_controllen qui contient des informations supplémentaires sur le paquet. Pour lire ce champ, vous devez d’abord déclarer un struct cmsghdr * (appelons-le cmhdr ). Vous CMSG_FIRSTHDR() ceci en appelant CMSG_FIRSTHDR() la première fois, en lui passant l’adresse de la structure msghdr et de CMSG_NXTHDR() chaque fois, en lui passant l’adresse de la structure msghdr et la valeur actuelle de cmhdr .

À partir de msg_control , vous pouvez trouver des choses intéressantes comme l’adresse IP de destination du paquet (utile pour la multidiffusion) et le contenu de l’octet TOS / DSCP dans l’en-tête IP (utile pour les protocoles de contrôle de congestion personnalisés). Dans la plupart des cas, vous devrez faire un appel à setsockopt pour permettre la réception de ces données. Dans les exemples donnés, les options IP_PKTINFO et IP_TOS doivent être activées.

Voir la page de manuel cmsg (3) pour plus de détails.

L’IP source et le port ne sont pas dans msg_control , mais dans msg_name qui attend un pointeur sur un struct sockaddr de longueur msg_namelen .

Voici un exemple d’utilisation:

 struct msghdr mhdr; struct iovec iov[1]; struct cmsghdr *cmhdr; char control[1000]; struct sockaddr_in sin; char databuf[1500]; unsigned char tos; mhdr.msg_name = &sin mhdr.msg_namelen = sizeof(sin); mhdr.msg_iov = iov; mhdr.msg_iovlen = 1; mhdr.msg_control = &control; mhdr.msg_controllen = sizeof(control); iov[0].iov_base = databuf; iov[0].iov_len = sizeof(databuf); memset(databuf, 0, sizeof(databuf)); if ((*len = recvmsg(sock, &mhdr, 0)) == -1) { perror("error on recvmsg"); exit(1); } else { cmhdr = CMSG_FIRSTHDR(&mhdr); while (cmhdr) { if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == IP_TOS) { // read the TOS byte in the IP header tos = ((unsigned char *)CMSG_DATA(cmhdr))[0]; } cmhdr = CMSG_NXTHDR(&mhdr, cmhdr); } printf("data read: %s, tos byte = %02X\n", databuf, tos); }