Socket non-bloquant bufferisé

Le
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.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Marc Boyer
Le #19160111
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...
espie
Le #19161011
In article 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....
Fançois Marc
Le #19161051
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.
-ed-
Le #19166271
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() ?
espie
Le #19167121
In article -ed-
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.
-ed-
Le #19172571
On 22 avr, 14:08, (Marc Espie) wrote:
In article
-ed-   >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 ...
espie
Le #19172681
In article -ed-
On 22 avr, 14:08, (Marc Espie) wrote:
In article



-ed-   >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
Publicité
Poster une réponse
Anonyme