2017-10-04 2 views
0

Ma compréhension de UDP était que, bien qu'il y ait une limitation de la taille MTU, si un datagramme dépasse le MTU, il sera fragmenté sur la couche IP, transmis en tant que paquets séparés, puis reconstruit à l'extrémité de réception. Si l'un des fragments est supprimé, la couche UDP supprimera tout le datagramme. Si tout arrive, la couche IP reconstruit le datagramme et UDP devrait le recevoir dans son ensemble.UDP .Receive() dans .NET renvoie un datagramme fragmenté en 1k parties

Ce n'est cependant pas le comportement que je vis. Voici une boucle simple serveur

var udp = new UdpClient(port); 

while (true) { 
    IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0); 

    byte[] payload = udp.Receive(ref remote); 

    Console.WriteLine($"Received {payload.Length}, IP: {remote}"); 
} 

et l'envoi de données via 2999 bytesnetcat comme suit

head -c 2999 /dev/urandom | nc -4u -w1 localhost 8999 

la boucle de serveur reçoit trois fois avec des charges utiles de taille 1024, 1024 et 951 octets. Depuis 2*1024 + 951 = 2999, il semble évident que les données que j'ai l'intention d'envoyer ont été réellement envoyées, mais le UdpClient le reçoit comme trois datagrammes différents.

Cela semble incompatible avec le fait que les couches UDP fonctionnent sur l'ensemble des datagrammes. Devrait-on implémenter leur propre logique de reconstruction de fragments en travaillant directement avec UDP? Ou existe-t-il un moyen de recevoir uniquement des datagrammes complets?

+0

Je ne suis pas un expert, mais par défaut [DontFragment] (https://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.dontfragment (v = vs.110) .aspx) est 'true', essayez de le définir sur false lors de la réception. Mais si vous prenez les sockets comme exemple, je m'attendrais à ce que vous soyez responsable des données combinées car la méthode 'Receive' va (comme il semble) simplement bloquer jusqu'à ce que les données soient reçues ou que le tampon soit plein, voir [cette question] stackoverflow.com/q/2319521/1997232) pour quelques conseils. – Sinatr

+0

La fragmentation se fait par les routeurs sur les paquets IP à la couche-3. TCP et UDP ne se fragmentent pas. Par exemple, les segments TCP, et c'est complètement différent de la fragmentation IP. –

Répondre

0

Votre compréhension de l'UDP est en effet correcte. Le protocole traitera la fragmentation et le réassemblage pour vous de manière transparente tant que tous les fragments arrivent à la destination. J'avais initialement pensé que head passait potentiellement vos données à netcat en morceaux de 1024 octets mais ce n'est pas le cas.

C'est en fait le scénario inverse: sur votre système, netcat lit stdin en blocs de 1024 octets et génère un nouveau paquet UDP à chaque fois. Il semble que netcat est le mieux utilisé pour traiter des flux continus de données qui sont la plupart du temps indifférents à la façon dont ils sont mis en paquets par les couches inférieures.

Plus d'informations sont disponibles au this StackOverflow question.