2010-05-11 5 views
2

Je suis actuellement en train d'exécuter un ancien système sur Tru64 qui implique beaucoup de sockets UDP en utilisant la fonction sendto(). Les sockets sont utilisés dans notre code pour envoyer des messages vers/depuis différents processus, puis éventuellement vers une application cliente connectée à distance. Parfois, le socket du client lourd est bloqué, ce qui peut entraîner l'accumulation de certains de ces messages. Ma question est comment puis-je déterminer la taille de la mémoire tampon actuelle, et comment puis-je déterminer le tampon de message maximale. Le code ci-dessous donne un extrait de comment je configure le port et utilise la fonction sendto.sendto sur Tru64 retourne ENOBUF

/* need to adjust the maximum size we can send on this */ 
/* as it needs to be able to cope with the biggest  */ 
/* messages we send         */ 

lenlen = sizeof(len) ; 

/* allow double for when the system is under load */ 
int     lenlen, len ; 
lenlen = sizeof(len) ; 
len = 2 * 32000; 

msg_socket = socket(AF_UNIX,SOCK_DGRAM, 0); 

result = setsockopt(msg_socket, SOL_SOCKET, SO_SNDBUF, (char *)&len, lenlen) ; 

    result = sendto(msg_socket, 
         (char *)message, 
         (int)message_len, 
         flags, 
         dest_addr, 
         addrlen); 

Remarque. Nous avons porté cette application sur Linux et le problème ne semble pas apparaître ici.

Toute aide serait grandement appréciée.

Cordialement

Répondre

0

Vous devriez probablement utiliser une sorte de contrôle de congestion pour éviter de surcharger le réseau. De loin, la façon la plus simple de le faire est d'utiliser TCP au lieu de UDP.

Il échoue moins souvent sur Linux parce que les sockets UDP attendent de l'espace dans la file d'attente de l'interface réseau local sous Linux (sauf si vous les définissez non bloquants). Cependant, avec n'importe quel système d'exploitation, si la file d'attente trop pleine n'est pas dans le système local, le paquet sera supprimé silencieusement.

2

La taille du tampon d'envoi UDP est différente de TCP - cela limite simplement la taille du datagramme. Citant Stevens UNP Vol. 1:

... Une socket UDP a une Taille du tampon (que nous pouvons changer avec SO_SNDBUF option prise, la section 7.5), mais cela est tout simplement une limite supérieure sur le datagramme UDP de taille maximale qui peut être écrit à la socket. Si une application écrit un datagramme plus grand que la taille du tampon d'envoi du socket, EMSGSIZE est renvoyé. Comme UDP n'est pas fiable, il n'a pas besoin de conserver une copie des données de l'application et n'a pas besoin d'un tampon d'envoi réel. (Les données d'application sont normalement copiées dans un tampon de noyau d'une forme telle qu'elle passe en bas de la pile de protocoles, mais cette copie est éliminé par la couche de liaison de données après que les données sont transmises.)
        UDP prepends simplement 8- octet et passe le datagramme à IP. IPv4 ou IPv6 ajoute son en-tête, détermine l'interface sortante en exécutant la fonction de routage, puis ajoute le datagramme à la file d'attente de sortie de liaison de données (s'il entre dans le MTU) ou fragmente le datagramme et ajoute chaque fragment à la file de sortie de liaison de données. Si une application UDO envoie de grands datagrammes (par exemple des datagrammes de 2 000 octets), la probabilité de fragmentation est beaucoup plus élevée qu'avec TCP. parce que TCP casse les données d'application en morceaux de taille MSS, quelque chose qui n'a pas de contrepartie en UDP.
        Le retour réussi de write à un socket UDP nous apprend que soit le datagramme ou tous les fragments du datagramme ont été ajoutés à la file d'attente de sortie de liaison de données. S'il n'y a pas de place dans la file d'attente pour le datagramme ou l'un de ses fragments, ENOBUFS est souvent renvoyé à l'application.
        Malheureusement, certaines implémentations ne renvoient pas cette erreur, donnant l'application aucune indication que le datagramme a été abandonnée sans même être transmis.

La dernière note a besoin d'attention - mais Tru64 semble avoir ce code d'erreur répertorié dans le manual page. La bonne façon de le faire est cependant de mettre en file d'attente vos messages en attente dans l'application elle-même et de vérifier soigneusement les valeurs de retour errno après chaque appel système. Cela ne garantit toujours pas la livraison (puisque les récepteurs UDP peuvent laisser tomber les paquets sans aucun préavis aux expéditeurs). Vérifiez les compteurs de suppression de paquets UDP avec netstat -s sur les deux/tous les côtés, voir s'ils sont en croissance. Il n'y a pas moyen de contourner cela en plus de passer à TCP ou de mettre en œuvre votre propre logique de timeout/ack et de retransmission.

Questions connexes