Perte de paquets UDP dans un thread quand l'autre thread fait un write() [Résolu]

cs_fabricius 4 Messages postés jeudi 31 juillet 2008Date d'inscription 10 novembre 2009 Dernière intervention - 3 juin 2009 à 14:34 - Dernière réponse :  Il_dodo
- 1 avril 2016 à 12:49
Hello,

Voila mon problème, ca fait bien une semaine que je suis dessus...
J'ai écrit un soft qui écoute une socket UDP, qui reçoit des paquets et qui les écrit sur disque. Et ce, pour plusieurs port donnés.
Le tout est en C++, sous linux, et utilise la libraire pthread. A chaque port UDP ecouté il y a deux threads: un qui ecoute la socket
l'autre qui se charge d'ecrire sur disque le buffer quand il est
suffisament gros.
Le probleme est que je perd des paquets, et je connais la cause: c'est la fonction write() qui s'effectue dans l'autre thread . Si je commente l'appel à la fonction write() alors je ne perd aucun paquet.
Pourtant cet appel système est censé etre ré-entrant, non ? Il ne devrait pas y avoir de soucis...

Je précise que les débits ne sont pas tres important: je commence à avoir des pertes à partir de 2 ports UDP qui envoient chacun à 20 Mo/s. Ce sont des petits paquets qui partent: de 300 a 500 octets. Et si j'augmente la taille des paquets, les pertes disparraissent.

Je commence à secher....
Afficher la suite 

Votre réponse

4 réponses

fregolo52 1108 Messages postés mercredi 15 juin 2011Date d'inscription 10 juillet 2018 Dernière intervention - 3 juin 2009 à 14:55
0
Merci
Essaie d'augmenter la taille du buffer de réception avec setsockopt.

Sinon, au niveau système, tu peux aussi augmenter la taille de la pile IP (surtout si tu es sous Linux).
Commenter la réponse de fregolo52
cs_fabricius 4 Messages postés jeudi 31 juillet 2008Date d'inscription 10 novembre 2009 Dernière intervention - 3 juin 2009 à 15:27
0
Merci
Hello,

merci de ta réponse. J'ai augmenté la taille de la variable net.core.rmem_max (avec la commande sysctl) mais ça n'a rien changé. Et pour les options de la socket, pareil, je crois que j'ai reduit un peu les pertes mais j'en ai toujours.

En fait plus j'y pense plus je me dit que c'est un soucis de synchronisation des threads, mais tout semble ok...
Commenter la réponse de cs_fabricius
fregolo52 1108 Messages postés mercredi 15 juin 2011Date d'inscription 10 juillet 2018 Dernière intervention - 3 juin 2009 à 15:38
0
Merci
dans un ancien projet, on balancait et recevait des trames multicast, c'était du violent niveau débit, style minimum 200Mb/s.
on a augmenté la pile, puis le buffer de réception, et ca allait mieux.
par défaut SO_RCVBUF est à 8200, on avait été tres haut je crois, style 160000.

pour la synchro des threads, on utilisait un semaphore, ce que tu as du faire.

après je vois pas, peut-etre l'écriture sur le HDD est super lente ?
Commenter la réponse de fregolo52
0
Merci
Bonjour,

je me permets de remonter le topic pour y apporter ma solution qui fonctionne presque entièrement. Il me reste un dernier problème que j'explique à la fin :

le problème ressemble beaucoup à celui que j'ai eu :
j'ai 12 process écoutant chacun sur un port udp différent avec des débits allant de 1 Mo/s à 100Mo/s, et des trames allant de 80 octets à 65507 (la taille max d'un paquet udp).
Je dois écrire en parallèle (2 threads par process : un qui reçoit, l'autre qui écrit) sur un SSD.
Les conditions pour que ça marche correctement sans perte de paquets :

1. Un disque ayant une vitesse d'écriture supérieure au débit total reçu. Ça parait évident, mais il faut quand même y faire bien attention : suivant le débit, tous les disques ne pourront pas forcément suivre. Pensez aussi que plus la taille à écrire est importante, plus le disque va être rapide à écrire => faites des fifo.

2. Faire 2 threads : 1 dédié à la réception des paquets udp, l'autre à l'écriture (ce que tu as fait)

3. Faire en sorte que les threads d'écriture et ceux de réception ne tournent pas sur le même cœur de ton processeur ! Ton problème vient probablement de là. Le disque va bloquer ton processeur pendant l'écriture réelle. Si le cœur qui s'occupe de l'écriture est sur le même cœur que celui qui s'occupe de la réception, tu peux effectivement perdre des paquets. Pour ma part, j'ai mis tous les threads d'écriture sur le même cœur, et j'ai réparti les threads de réception entre les autres cœurs.

4. Pour la transmission de gros paquets UDP avec un débit important, passez en jumbo frame. Évidemment, il faut que l'émetteur, le récepteur, mais aussi tous les intermédiaires entre l'émetteur et le récepteur (commes les switchs) passent en jumbo frame.


Malgré cela, et c'est mon problème qui demeure, il m'arrive de perdre le tout 1er paquet. Quelqu'un a-t-il une idée pour dépanner ?
Commenter la réponse de Il_dodo

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.