web-dev-qa-db-fra.com

Que feraient tomber les paquets UDP lors de l'envoi à Localhost?

J'envoie de très grands (64000 octets) datagrammes. Je me rends compte que le MTU est beaucoup plus petit que 64 000 octets (une valeur typique est d'environ 1500 octets, de ma lecture), mais je soupçonnerais que l'une des deux choses se produirait - ni aucun datagramme ne le ferait à travers (tout de plus de 1500 octets serait déposé silencieusement ou causer une erreur/une exception à jeter) ou que les datagrammes de 64 000 octets seraient mordu dans environ 43 minutes d'octets et transmises de manière transparente.

Sur une longue course (plus de 2000 64000 datagrammes d'octets), environ 1% (qui semble anormalement élevée pour même un réseau local) des datagrammes sont supprimés. Je pourrais vous attendre à ce que ceci sur un réseau, où les datagrammes peuvent arriver en panne, être tombés, filtrés, etc. Cependant, je ne m'attendais pas à cela lors de la course sur Localhost.

Qu'est-ce qui cause l'incapacité d'envoyer/recevoir des données localement? Je réalise que UDP n'est pas fiable, mais je ne m'attendais pas à ce qu'il soit si peu fiable sur Localhost. Je me demande si ce n'est qu'un problème de synchronisation car les composants d'envoi et de réception sont sur la même machine.

Pour complétude, j'ai inclus le code pour envoyer/recevoir des datagrammes.

Envoi en cours:

DatagramSocket socket = new DatagramSocket(senderPort);

int valueToSend = 0;

while (valueToSend < valuesToSend || valuesToSend == -1) {
    byte[] intBytes = intToBytes(valueToSend);

    byte[] buffer = new byte[bufferSize - 4];

     //this makes sure that the data is put into an array of the size we want to send
    byte[] bytesToSend = concatAll(intBytes, buffer);

    System.out.println("Sending " + valueToSend + " as " + bytesToSend.length + " bytes");

    DatagramPacket packet = new DatagramPacket(bytesToSend,
                        bufferSize, receiverAddress, receiverPort);

    socket.send(packet);

    Thread.sleep(delay);

    valueToSend++;
}

Recevoir:

DatagramSocket socket = new DatagramSocket(receiverPort);

while (true) {
    DatagramPacket packet = new DatagramPacket(
            new byte[bufferSize], bufferSize);

    System.out.println("Waiting for datagram...");
    socket.receive(packet);

    int receivedValue = bytesToInt(packet.getData(), 0);

    System.out.println("Received: " + receivedValue
            + ". Expected: " + expectedValue);

    if (receivedValue == expectedValue) {
        receivedDatagrams++;
        totalDatagrams++;
    }
    else {
        droppedDatagrams++;
        totalDatagrams++;
    }

    expectedValue = receivedValue + 1;
    System.out.println("Expected Datagrams: " + totalDatagrams);
    System.out.println("Received Datagrams: " + receivedDatagrams);
    System.out.println("Dropped Datagrams: " + droppedDatagrams);
    System.out.println("Received: "
            + ((double) receivedDatagrams / totalDatagrams));
    System.out.println("Dropped: "
            + ((double) droppedDatagrams / totalDatagrams));
    System.out.println();
}
22
Thomas Owens

UDP PKTS La planification peut être traitée par plusieurs threads au niveau du système d'exploitation. Cela expliquerait pourquoi vous les recevez hors de commande même sur 127.0.0.1.

4
Niko

Vos attentes, telles qu'exprimées dans votre question et dans de nombreux commentaires à d'autres réponses, sont fausses. Tout ce qui suit peut arriver même en l'absence de routeurs et de câbles.

  1. Si vous envoyez un paquet à n'importe quel récepteur et qu'il n'y a pas de place dans sa prise tampon de réception, elle sera chutée.

  2. Si vous envoyez un datagramme UDP plus grand que le chemin MTU, il sera fragmenté en paquets plus petits, qui sont soumis à (1).

  3. Si tous les paquets d'un datagramme n'arrivent pas, le datagramme ne sera jamais livré.

  4. La pile TCP/IP n'a aucune obligation de livrer des paquets ou des datagrammes UDP dans l'ordre.

1
user207421

Je ne sais pas ce qui vous fait attendre un pourcentage de moins de 1% des paquets abandonnés pour UDP.

Cela étant dit, sur la base de - RFC 1122 (voir section 3.3.2 ), la taille maximale de la mémoire tampon garantie ne pas être divisée en plusieurs datagrammes IP est de 576 octets. Les datagrammes UDP plus gros peuvent être transmis, mais ils seront probablement divisés en plusieurs datagrammes IP pour être réassemblés au point de fin de réception.

J'imagine qu'une raison de contribuer au taux élevé de paquets abandonnés que vous voyez est que si un paquet IP faisait partie d'un grand datagramme UDP est perdu, tout le datagramme UDP sera perdu. Et vous comptez des datagrammes UDP - pas des paquets IP.

0
Mike Dinescu

Les paquets UDP ne sont pas garantis pour atteindre leur destination alors que TCP est!

0
r0ast3d