Les paquets UDP Winsock sont-ils abandonnés?

Nous avons un système de communication client / serveur sur la configuration UDP dans Windows. Le problème auquel nous sums confrontés est que, lorsque le débit augmente, les paquets sont abandonnés. Nous pensons que cela est dû au tampon de réception UDP qui est continuellement interrogé, le bloquant et laissant tomber les paquets entrants. Est-il possible que la lecture de cette mémoire tampon entraîne la suppression des paquets entrants? Si oui, quelles sont les options pour corriger cela? Le système est écrit en C. S’il vous plaît laissez-moi savoir si cela est trop vague et je peux essayer de fournir plus d’informations. Merci!

La taille du tampon de socket par défaut dans les sockets Windows est de 8 Ko, soit 8 192 octets. Utilisez la fonction Windows de setsockopt pour augmenter la taille du tampon (reportez-vous à l’option SO_RCVBUF).

Mais au-delà, augmenter la taille de votre tampon de réception ne fera que retarder le rejet des paquets si vous ne les lisez pas assez rapidement.

En règle générale, vous voulez deux threads pour ce genre de situation.

Le premier thread existe uniquement pour desservir le socket. En d’autres termes, le seul but du fil est de lire un paquet dans la socket, de l’append à une sorte de structure de données partagée correctement synchronisée, de signaler qu’un paquet a été reçu, puis de lire le paquet suivant.

Le deuxième thread existe pour traiter les paquets reçus. Il rest inactif jusqu’à ce que le premier thread signale qu’un paquet a été reçu. Il extrait ensuite le paquet de la structure de données partagée correctement synchronisée et le traite. Il attend ensuite d’être à nouveau signalé.

En guise de test, essayez de court-circuiter le traitement complet de vos paquets et écrivez simplement un message sur la console (ou un fichier) chaque fois qu’un paquet est reçu. Si vous réussissez à le faire sans perdre de paquets, alors diviser votre fonctionnalité en un thread “récepteur” et un thread “en traitement” vous aidera.

Oui, la stack est autorisée à déposer des paquets – même silencieusement – lorsque ses tampons sont trop pleins. Cela fait partie de la nature du protocole UDP, l’un des éléments de fiabilité que vous perdez lorsque vous passez de TCP. Vous pouvez soit réinventer TCP – de manière médiocre – en ajoutant une logique de nouvelle tentative, des paquets ACK, etc., soit vous pouvez basculer vers un système intermédiaire, tel que SCTP .

Il existe des moyens d’augmenter la taille de la mémoire tampon de la stack, mais cela passe à côté de l’essentiel. Si vous ne lisez pas assez rapidement pour garder de la mémoire tampon déjà disponible, le fait d’agrandir les mémoires tampons ne fera que retarder le temps qu’il vous faut pour manquer d’espace tampon. La solution appropriée consiste à créer des tampons plus importants dans votre propre code et à déplacer les données des tampons de la stack dans le tampon ASAP de votre programme, où elles peuvent attendre d’être traitées pendant des durées arbitrairement longues.

Est-il possible que la lecture de cette mémoire tampon entraîne la suppression des paquets entrants?

Les paquets peuvent être abandonnés s’ils arrivent plus rapidement que vous ne les lisez.

Si oui, quelles sont les options pour corriger cela?

Une option consiste à modifier le protocole réseau: utilisez TCP, ou implémentez un accusé de réception + ‘contrôle de stream’ en utilisant UDP.

Sinon, vous devez voir pourquoi vous ne lisez pas assez vite.

Si le processeur est utilisé à 100%, vous devez faire moins de travail par paquet ou obtenir un processeur plus rapide (ou utiliser le multithreading et davantage de processeurs si vous ne l’êtes pas déjà).

Si le processeur n’est pas à 100%, alors peut-être que ce qui se passe est:

  • Tu lis un paquet
  • Vous effectuez un travail qui prend x ms de temps réel, dont une partie est bloquée sur une autre entrée / sortie (le processeur n’est donc pas occupé, mais il n’est pas utilisé pour lire un autre paquet)
  • Au cours de ces x msec, un flot de paquets arrive et certains sont abandonnés

Un remède à cela serait de changer le filetage.

Une autre possibilité consiste à effectuer plusieurs lectures simultanées à partir du socket (chacune de vos lectures fournit un tampon dans lequel un paquet UDP peut être reçu).

Une autre possibilité consiste à vérifier s’il existe une option de configuration (spécifique à l’O / S) permettant d’augmenter le nombre de paquets UDP reçus que la stack de réseau souhaite mettre en mémoire tampon jusqu’à ce que vous essayiez de les lire.

Première étape, augmenter la taille de la mémoire tampon du récepteur, Windows accorde pratiquement toutes les demandes de taille raisonnable.

Si cela ne vous aide pas, votre code de consommation semble avoir des zones assez lentes. J’utiliserais les threads, par exemple avec pthreads, et utiliserais un modèle de consommateur producteur pour mettre le datagramme entrant dans une queue sur un autre thread, puis consumr à partir de là, pour que vos appels reçus ne se bloquent pas et que la mémoire tampon ne soit pas saturée

3ème étape, modifiez votre protocole au niveau de l’application, autorisez l’envoi de paquets en lots et de paquets en lots afin de réduire la surcharge d’en-tête UDP liée à l’envoi d’un grand nombre de petits paquets.

La 4e étape de la vérification de votre équipement réseau, de vos commutateurs, etc. peut vous donner des informations détaillées sur les statistiques de trafic, les débordements de mémoire tampon, etc. – en cas de problème, obtenez des commutateurs plus rapides ou éventuellement en éteignez un défectueux.

… juste pour le moment, j’utilise en permanence le trafic de multidiffusion UDP sur notre serveur principal. ~ 30 Mbit / s avec des pics de 70 Mbit / s et mon taux de chute est nu

Pas sûr, mais sous Windows, il n’est pas possible d’interroger la socket et de faire tomber un paquet. Windows collecte les paquets séparément de votre interrogation et cela ne devrait causer aucune chute.

Je suppose que vous utilisez select () pour interroger la socket? Pour autant que je sache, ne peut pas causer une chute.