Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Socket non-bloquant bufferisé

7 réponses
Avatar
Fançois Marc
Bonjour,

Je peine à déceler l'origine d'un problème lié à l'utilisation des
sockets réseaux non-bloquants en tant que flux bufferisé. Peut être
aurez vous l'explication.

Soit 'sock' un socket non-bloquant:

FILE * dst = fdopen(sock, "r+");

Soit 'data' une ligne lue parmi 100.000 lignes, et une boucle exécutant:
fputs(data, dst);
fflush(dst);

Le problème est que je ne reçois pas toujours la totalité de ce que j'ai
envoyé. Si il y a des "trous" (un certain nombre de lignes consécutives
manquantes) alors la dernière ligne reçue est toujours incomplète.
Le problème commence à apparaître avec un nombre de lignes envoyées > à
20.000. En dessous de ce nombre, toutes les lignes envoyées sont reçues.

Tout cela m'amène à penser qu'il s'agit d'un problème lié au fait que le
buffer attribué à 'dst' est plein. Et qu'il se re-rempli bien plus vite
qu'il ne se vide. (Existe t-il d'ailleurs un moyen de connaître son taux
d'occupation ?)

Pendant toute la durée du traitement, fputs ne retourne jamais d'erreur.
Ce n'est pas le cas que fflush qui commence à renvoyer des EAGAIN à
répétition à l'approche des 20.000 lignes.
Le simple fait d'intercaler un sleep(3) après chaque erreur de fflush
suffit à limiter la perte à une ou deux lignes sur les 100.000.

En passant 'dst' en mode non-bufferisé ou bufferisé en ligne, _IONBF ou
_IOLBF, le problème est réglé. Mais j'aimerai comprendre ce qu'il se
passe dans le cas présenté pour ne pas mourir idiot.

Merci.

7 réponses

Avatar
Marc Boyer
On 2009-04-21, Fançois Marc <none> wrote:
Bonjour,

Je peine à déceler l'origine d'un problème lié à l'utilisation des
sockets réseaux non-bloquants en tant que flux bufferisé. Peut être
aurez vous l'explication.



Je ne suis pas spécialiste de la question, mais en attendant que
quelqu'un précise, quelques remarques.

Soit 'sock' un socket non-bloquant:

FILE * dst = fdopen(sock, "r+");

Soit 'data' une ligne lue parmi 100.000 lignes, et une boucle exécutant:
fputs(data, dst);
fflush(dst);

Le problème est que je ne reçois pas toujours la totalité de ce que j'ai
envoyé. Si il y a des "trous" (un certain nombre de lignes consécutives
manquantes) alors la dernière ligne reçue est toujours incomplète.
Le problème commence à apparaître avec un nombre de lignes envoyées > à
20.000. En dessous de ce nombre, toutes les lignes envoyées sont reçues.



Tout d'abord, précisons que cela n'est pas un problème de C (d'où mon
cross-post et fu2), mais lié aux sockets (et le fait que les socket aient
une API en C ne signifie pas qu'ils soient du C). Je fais le fu2 vers
fr.comp.os.unix car même s'il n'y a pas que là qu'il y a des sockets,
historiquement, ils en viennent.

Tout cela m'amène à penser qu'il s'agit d'un problème lié au fait que le
buffer attribué à 'dst' est plein. Et qu'il se re-rempli bien plus vite
qu'il ne se vide.



Surement.
Déjà, est-ce que tu as ouvert un socket UDP ou TCP ? En UDP, ton problème
est normal (pas de controle de flux). Si ça apparait en TCP, c'est plus
génant.

Marc Boyer
--
Au XXIème siècle, notre projet de société s'est réduit
à un projet économique...
Avatar
espie
In article <49edb125$0$20526$,
Fançois Marc <none> wrote:
Bonjour,

Je peine à déceler l'origine d'un problème lié à l'utilisation des
sockets réseaux non-bloquants en tant que flux bufferisé. Peut être
aurez vous l'explication.

Soit 'sock' un socket non-bloquant:

FILE * dst = fdopen(sock, "r+");

Soit 'data' une ligne lue parmi 100.000 lignes, et une boucle exécutant:
fputs(data, dst);
fflush(dst);



Tu n'as pas de garantie que la bibliotheque standard soit au courant des
entrees-sorties non-bloquantes. Dans le code que j'ai sous la main, je
vois des write(2), avec traitement uniforme de toutes les erreurs, et
pas de cas particulier pour EGAIN, qui va donc remonter "tres vite"
a l'utilisateur....
Avatar
Fançois Marc
Marc Boyer wrote:
Tout d'abord, précisons que cela n'est pas un problème de C (d'où mon
cross-post et fu2), mais lié aux sockets (et le fait que les socket aient
une API en C ne signifie pas qu'ils soient du C). Je fais le fu2 vers
fr.comp.os.unix car même s'il n'y a pas que là qu'il y a des sockets,
historiquement, ils en viennent.



Merci pour le fu2, et désolé de ne pas y avoir pensé.

Déjà, est-ce que tu as ouvert un socket UDP ou TCP ? En UDP, ton problème
est normal (pas de controle de flux). Si ça apparait en TCP, c'est plus
génant.



Il s'agit d'un socket TCP.
Avatar
-ed-
On 21 avr, 13:42, Fançois Marc <none> wrote:
Bonjour,

Je peine à déceler l'origine d'un problème lié à l'utilisation des
sockets réseaux non-bloquants en tant que flux bufferisé. Peut être
aurez vous l'explication.

Soit 'sock' un socket non-bloquant:

        FILE * dst = fdopen(sock, "r+");

Soit 'data' une ligne lue parmi 100.000 lignes, et une boucle exécutant :
        fputs(data, dst);
        fflush(dst);



Quel intérêt de passer par les flux bufférisés ? On ajoute une couc he
logicielle. Est-ce bien nécessaire ? Est-ce que ça fonctionne
'normalement', c'est à dire avec recv() ?
Avatar
espie
In article ,
-ed- wrote:
Quel intérêt de passer par les flux bufférisés ? On ajoute une couche
logicielle. Est-ce bien nécessaire ? Est-ce que ça fonctionne
'normalement', c'est à dire avec recv() ?



Ca permet de reutiliser du code qui manipule directement des FILE *....
apres un moment, la reinvention de la roue, ca lasse.
Avatar
-ed-
On 22 avr, 14:08, (Marc Espie) wrote:
In article .com>,

-ed-   wrote:
>Quel intérêt de passer par les flux bufférisés ? On ajoute une c ouche
>logicielle. Est-ce bien nécessaire ? Est-ce que ça fonctionne
>'normalement', c'est à dire avec recv() ?

Ca permet de reutiliser du code qui manipule directement des FILE *....
apres un moment, la reinvention de la roue, ca lasse.



Bah, le traitement des réception par sockets ça se fait en une
fonction que l'on classe dans sa bibliothèque perso... Pas besoin de
passer par un fdopen() non portable qui ne fonctionnera pas sous
Windows...

De plus, visiblement, ça introduit des comportements peu clairs ...
Avatar
espie
In article ,
-ed- wrote:
On 22 avr, 14:08, (Marc Espie) wrote:
In article


,

-ed-   wrote:
>Quel intérêt de passer par les flux bufférisés ? On ajoute une couche
>logicielle. Est-ce bien nécessaire ? Est-ce que ça fonctionne
>'normalement', c'est à dire avec recv() ?

Ca permet de reutiliser du code qui manipule directement des FILE *....
apres un moment, la reinvention de la roue, ca lasse.



Bah, le traitement des réception par sockets ça se fait en une
fonction que l'on classe dans sa bibliothèque perso... Pas besoin de
passer par un fdopen() non portable qui ne fonctionnera pas sous
Windows...



De plus, visiblement, ça introduit des comportements peu clairs ...



Woah. Si tu veux traiter pas mal de protocoles classiques, c'est plutot bien
d'avoir des entrees-sorties "classiques". Par contre, ca va plutot se gerer
a coups de select qu'a coups d'entrees-sorties non bloquantes.

Pas portable sous windows ? en l'occurrence, rien a foutre. Si je veux du
socket portable sous windows, je vais faire du perl de toutes facons