Lire depuis la prise

Je dois lire un socket AF_UNIX dans un tampon en utilisant la fonction read C, mais je ne connais pas la taille du tampon.

Je pense que le meilleur moyen est de lire N octets jusqu’à ce que la lecture renvoie 0 (plus d’écrivains dans le socket). Est-ce correct? Existe-t-il un moyen de deviner la taille du tampon en cours d’écriture sur le socket?

Je pensais qu’une socket est un fichier spécial. Ouvrir le fichier en mode binary et obtenir la taille me permettrait de connaître la taille correcte à donner au tampon?

Je suis un nouveau venu dans C, alors s’il vous plaît gardez cela à l’esprit.

La méthode la plus courante consiste à utiliser ioctl(..) pour interroger FIONREAD du socket, ce qui renverra la quantité de données disponibles.

 int len = 0; ioctl(sock, FIONREAD, &len); if (len > 0) { len = read(sock, buffer, len); } 

Une façon de lire une quantité inconnue du socket tout en évitant le blocage pourrait consister à interroger () un socket non bloquant pour les données.

Par exemple

 char buffer[1024]; int ptr = 0; ssize_t rc; struct pollfd fd = { .fd = sock, .events = POLLIN }; poll(&fd, 1, 0); // Doesn't wait for data to arrive. while ( fd.revents & POLLIN ) { rc = read(sock, buffer + ptr, sizeof(buffer) - ptr); if ( rc <= 0 ) break; ptr += rc; poll(&fd, 1, 0); } printf("Read %d bytes from sock.\n", ptr); 

Je pense que le meilleur moyen est de lire N octets jusqu’à ce que la lecture renvoie 0 (plus d’écrivains dans le socket). Est-ce correct?

0 signifie EOF, l’autre côté a fermé la connexion. Si l’autre côté de la communication ferme la connexion, alors c’est correct.

Si la connexion n’est pas fermée (transferts multiples sur la même connexion, protocole bavard), le cas est un peu plus compliqué et le comportement dépend généralement du type de socket SOCK_STREAM ou SOCK_DGRAM.

Les sockets de datagramme sont déjà délimités pour vous par le système d’exploitation.

Les sockets de stream ne délimitent pas les messages (toutes les données sont un stream d’octets opaque) et, si vous le souhaitez, vous devez les implémenter au niveau de l’application: par exemple, en définissant un champ de taille dans la structure d’en-tête de message ou en utilisant un délimiteur (par exemple ‘\ n’ pour messages texte d’une seule ligne). Dans le premier cas, vous devriez d’abord lire l’en-tête, extraire la longueur et lire le rest du message. Dans les autres cas, lisez le stream dans le tampon partiel, recherchez le délimiteur et extrayez-le du message contenant le délimiteur (vous devrez peut-être conserver le tampon partiel car, en fonction du protocole, plusieurs commandes peuvent être reçues avec recv () / read ( )).

Existe-t-il un moyen de deviner la taille du tampon en cours d’écriture sur le socket?

Pour les sockets de stream, il n’existe aucun moyen fiable, car l’autre partie de la communication est peut-être encore en train d’écrire les données. Imaginons le cas tout à fait normal: le tampon de socket est de 32K et 128K est en cours d’écriture. L’écriture d’une application bloque à l’intérieur de send () / write (), le système d’attente en attente de lecture de l’application pour lire les données, libérant ainsi de l’espace pour le prochain bloc de données écrites.

Pour les sockets de datagramme, on connaît normalement la taille du message à l’avance. Ou bien on peut essayer (je ne l’ai jamais fait moi-même) recvmsg (MSG_PEEK) et si le MSG_TRUNC se trouve dans le msghdr.msg_flags renvoyé, essayez d’augmenter la taille de la mémoire tampon.

vous avez raison, si vous ne connaissez pas la taille de l’entrée, vous pouvez simplement lire un octet à chaque fois et l’append à une mémoire tampon plus grande.

read N octets jusqu’à ce que la lecture renvoie 0

Oui!

Un détail ajouté. Si l’expéditeur ne ferme pas la connexion, le socket bloquera au lieu de revenir. Une socket non bloquante renverra -1 (avec errno == EAGAIN = = errno == EAGAIN ) lorsqu’il n’y a rien à lire; c’est un autre cas.

Ouvrir le fichier en mode binary et obtenir la taille me permettrait de connaître la taille correcte à donner au tampon?

Nan. Les sockets n’ont pas de taille. Supposons que vous envoyiez deux messages via la même connexion: Quelle est la longueur du fichier?