[gull] socket en C

Leopoldo Ghielmetti leopoldo.ghielmetti at a3.epfl.ch
Thu May 15 12:01:18 CEST 2008


Il giorno gio, 15/05/2008 alle 11.33 +0200, Christian ALT ha scritto:
> Bonjour,
> 
> Désolé si je sauté dans la discussion sans avoir lu tout le détail, mais lorsque je lis qu'une application sur un réseau local dépend du type de machine ou de son OS cela me fait m'interroger. Vos sockets travaillent sur UDP ou TCP?

C'est une application TCP et le comportement est tout à fait normal.

> La différence c'est le mode orienté connexion ou pas. UDP est coûteux sur un réseau ou il y a des erreurs de transmission ou des congestions. Ce qui caractérise votre cas. Et surtout que le contrôle de flux doit être géré au niveau de l'application. C'est ce qui manque dans ce que je comprends de votre problème et qui me fait réagir.

Si dans le code tu écris:
write("toto");
...
write("titi");
...
write("tata");

selon la gestion des taches du système, tu peux avoir trois envoies d'un
paquets de 4 bytes avec toto, titi, tata ou un seul envoie d'un gros
paquet contenant tototititata (voir d'autres combinaisons, p.e. "totot"
et "ititata").

J'ai très souvent vu des gens qui écrivent le code opposé comme:
read(a);
...
read(b);
...
read(c);

en s'attendant trois fois 4 caractères, ce qui est totalement faux.

Ça peux marcher si la première machine est très lente et prends beaucoup
de temps è traiter chaque write ou si elle est chargée et les task
switch font en sorte que les trois write correspondent à l'envoi de
trois paquets.
Par contre la machine opposée devra être très rapide pour traiter les
trois messages dès qu'ils arrivent, sinon elle se retrouvera avec une
chaîne à la tototititata. et pas 3 fois 4 caractères.

C'est exactement le cas ou en changeant un jota dans la configuration de
la machine, l'OS ou le réseau, tu risques qu'une application qui a
toujours marché commence à se comporter bizarrement.

Il est bien sur possible de dire à la commande read quelle est la taille
des données à lire, mais si on s'attend à un message de 200 bytes et on
en reçoit seulement 190, ça ne veut pas dire que le paquet est corrompu,
simplement il y a des chances que les 10 bytes manquants vont arriver un
peu plus tard (peut être même collés en début du paquet suivant). Ce
découpage est totalement indépendant de l'application.

C'est de la très mauvaise programmation, mais la plupart des gens qui
commencent à programmer socket font cette erreur, et il y a 8 ans, quand
j'ai commencé à écrire l'application dont je parlais je l'ai fait aussi.
Je me suis heureusement rendu compte de l'erreur encore pendant les
premières 2 semaines de développement et j'ai pu écrire une application
solide, mais ce n'a pas été le cas pour tout le monde.

L'autre application dont je parlais fait exactement part de ces codes
mal écrits. C'est un fournisseur qui avait fourni un de nos clients avec
un tel logiciel, et pendant 5 ans tout à bien fonctionné, jusqu'au jour
ou on a eu comme mandat de remplacer les serveurs qu'on gérait, on a mis
des machines plus puissantes (justement les Xeon) et l'application de
l'autre côté a commencé à planter régulièrement (une fois pas semaine au
moins). Dès que j'ai vu le comportement j'ai immédiatement supposé que
le problème venait de la et j'ai signalé le problème au fournisseur.
Malheureusement c'était une application non plus maintenue (non open
bien évidemment) et donc le client à du s'organiser pour rebooter les
machines une ou deux fois par semaine quand l'application plantait.
A la fin ils ont aussi remplacé ces machines et ils ont pris une
application plus récente et tout est rentré dans l'ordre.

Et le tout simplement parce que le fournisseur (qui me l'a confirmé) ne
faisait qu'un simple read en s'attendant à recevoir un paquet complet et
un seul. Ce qui était bien le cas tant que les machines étaient assez
équilibrées, mais qui ne marchait plus du tout au moment ou les machines
ne l'étaient plus.

ciao, Leo

> C'était une remarque en vitesse.
> 
> Bonne journée,
> 
> 
> Christian ALT
> 
> Telecom and Logistics Associates
> Network Security Company
> Security Lead Auditor for ISO 27001
> http://www.tla.ch
> Agenda Romand de la formation IT et Securité
> http://www.tla.ch/agenda.htm 
> 
> 
> 
> 
> -----Original Message-----
> From: gull-bounces at forum.linux-gull.ch [mailto:gull-bounces at forum.linux-gull.ch] On Behalf Of Leopoldo Ghielmetti
> Sent: jeudi, 15. mai 2008 11:07
> To: GULL (Liste technique)
> Subject: Re: [gull] socket en C
> 
> 
> Il giorno gio, 15/05/2008 alle 10.21 +0200, Yann Sagon ha scritto:
> > Leopoldo Ghielmetti a crit :
> > > Il giorno mer, 14/05/2008 alle 16.42 +0200, Marc Mongenet ha scritto:
> ...
> > > Exact. Il faut faire un accept et traiter la connexion. La boucle qui
> > > fait les accept doit toujours tourner, simplement si le nombre maximum
> > > de connexion autorises est atteint, la boucle peut envoyer un message
> > > et dconnecter juste aprs.
> > > Regarde aussi du ct du nombre de client en attente sur le socket (je
> > > ne me rappelle plus comment s'appelle le paramtre, mais a  a voir
> > > avec un paramtre listener ou qqc. comme a), 
> > dans listen tu peux spcifier le "backlog" soit les clients en attente, 
> > je pense que c'est de a que tu parles? C'est 5 normalement.
> 
> Oui, c'est exactement de a. Tout dpend de combien de client en attente
> tu t'attends. 5 est suffisant, si par contre tu risque d'avoir des rush
> de 10 ou 20 clients  la fois alors il est peut-tre prfrable
> d'augmenter la valeur pour avoir le temps de traiter les connexions.
> Mais je pense que c'est un paramtre que tu peux rgler uniquement aprs
> experience.
> 
> > > Fais aussi trs attention aux paquets "fragmentes" lors-ce que tu traite
> > > tes read/write sur le socket, ne fais jamais de suppositions sur les
> > > donnes envoys ou reues, mme si c'est ton code qui les envoie, il est
> > > toujours possible que tu fais un write("toto\n") et que de l'autre ct
> > > tu reois un "to" et une seconde aprs "to\n", ou que tu fais
> > > write("toto\n"); sleep(1000);write("titi\n") et que tu reois "toto
> > > \ntiti\n" en un seul coup.
> > >   
> > C'est une application qui sera utilise sur un rseau local, il n'y aura 
> > (en principe) jamais de fragrmentation.
> > Mais effectivement, vaut mieux prvoir..
> 
> Dtrompes toi, on a eu ce problme sur un rseau local  1Gbps entre 2
> machines sur le mme switch. Et ce uniquement parce qu'une machine tait
> un Xeon 3GHz et l'autre un Pentium III  800MHz (ou quelque chose du
> style).
> Quand le Xeon envoyait ses paquets, le Pentium les mettait en queue car
> il n'arrivait pas  les traiter, donc on se retrouvait avec les paquets
> concatns. Quand le Pentium envoyait des paquets au Xeon, si le message
> tait assez gros, le message tait coup par le Xeon car il tait trop
> rapide et il commenait  traiter le paquet avant que le Pentium ait
> termin la transmission.
> Il faut aussi considrer que le systme d'exploitation peut dcider
> d'envoyer une partie du buffer pour des questions bien  lui, mme si
> aucun "\n" n'a t transmis ou aucun flush n'a t demand.
> 
> C'est pour a que je dis qu'il ne faut jamais faire des suppositions sur
> la faon dont les donnes sont envoyes ou reues, tu met  jour une
> machine, un OS ou tu changes un switch et tout foire.
> 
> ciao, Leo
> 
> _______________________________________________
> gull mailing list
> gull at forum.linux-gull.ch
> http://forum.linux-gull.ch/mailman/listinfo/gull
> 
> No virus found in this incoming message.
> Checked by AVG. 
> Version: 7.5.524 / Virus Database: 269.23.16/1433 - Release Date: 14.05.2008 16:44
>  
> 
> No virus found in this outgoing message.
> Checked by AVG. 
> Version: 7.5.524 / Virus Database: 269.23.16/1433 - Release Date: 14.05.2008 16:44
>  
> 
> 
> _______________________________________________
> gull mailing list
> gull at forum.linux-gull.ch
> http://forum.linux-gull.ch/mailman/listinfo/gull




More information about the gull mailing list