2012-09-06 19 views
8

Non avevo mai usato l'UDP prima, quindi ho provato. Per vedere cosa succederebbe, ho avuto il 'server' inviare i dati ogni mezzo secondo, e il client riceve i dati ogni 3 secondi. Pertanto, anche se il server invia i dati molto più rapidamente di quanto possa ricevere il client, il client lo riceve ancora in modo ordinato uno per uno.Dove vengono memorizzati i dati inviati da UDP?

Qualcuno può spiegare perché/come ciò accade? Dove si trova esattamente il buffer dei dati?

Invia

class CSimpleSend 
{ 
    CSomeObjServer obj = new CSomeObjServer(); 

    public CSimpleSend() 
    { 
     obj.changedVar = varUpdated; 
     obj.threadedChangeSomeVar(); 
    } 

    private void varUpdated(int var) 
    { 
     string send = var.ToString(); 
     byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(send); 

     string ip = "127.0.0.1"; 
     int port = 11000; 

     IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port); 
     Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
     client.SendTo(packetData, ep); 

     Console.WriteLine("Sent Message: " + send); 
     Thread.Sleep(100); 
    } 
} 

Tutti CSomeObjServer non c'è da incrementare un numero intero di uno ogni mezzo secondo

Ricevi

class CSimpleReceive 
{ 
    CSomeObjClient obj = new CSomeObjClient(); 

    public Action<string> showMessage; 
    Int32 port = 11000; 
    UdpClient udpClient; 


    public CSimpleReceive() 
    { 
     udpClient = new UdpClient(port); 

     showMessage = Console.WriteLine; 
     Thread t = new Thread(() => ReceiveMessage()); 
     t.Start(); 
    } 

    private void ReceiveMessage() 
    {      
     while (true) 
     { 
      //Thread.Sleep(1000); 
      IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port); 
      byte[] content = udpClient.Receive(ref remoteIPEndPoint); 

      if (content.Length > 0) 
      { 
       string message = Encoding.UTF8.GetString(content); 
       if (showMessage != null) 
        showMessage("Recv:" + message); 

       int var_out = -1; 
       bool succ = Int32.TryParse(message, out var_out); 
       if (succ) 
       { 
        obj.alterSomeVar(var_out); 
        Console.WriteLine("Altered var to :" + var_out); 
       } 
      } 
      Thread.Sleep(3000); 
     } 
    } 
} 

negozi CSomeObjClient la variabile e ha una funzione (alterSomeVar) per aggiornarlo

Ouput:

Sent Message: 1 
Recv:1 
Altered var to :1 
Sent Message: 2 
Sent Message: 3 
Sent Message: 4 
Sent Message: 5 
Recv:2 
Altered var to :2 
Sent Message: 6 
Sent Message: 7 
Sent Message: 8 
Sent Message: 9 
Sent Message: 10 
Recv:3 
Altered var to :3 
+3

Plaudo vostra natura curiosa, +1 – spender

+1

il sistema operativo ha uno stack di rete che di solito ha alcuni buffer ... fino a quando ciò che si invia si inserisce in questi buffer senza problemi ... poiché UDP non è garantito, in ogni caso i dati potrebbero essere scartati, ecc. – Yahia

+0

Il client e il server sono in esecuzione sulla stessa macchina? – grieve

risposta

3

Il kernel del sistema operativo mantiene buffer di invio e ricezione separati per ogni socket UDP e TCP. Se cerchi su google SO_SNDBUF e SO_RCVBUF troverai molte informazioni su di loro.

Quando si inviano dati, vengono copiati dallo spazio applicazioni nel buffer di invio. Da lì viene copiato sulla scheda di interfaccia di rete e quindi sul filo. Il lato di ricezione è il contrario: NIC per ricevere il buffer, dove attende finché non lo leggi. Inoltre, possono verificarsi anche copie e buffering, a seconda del sistema operativo.

È fondamentale notare che le dimensioni di questi buffer possono variare radicalmente. Alcuni sistemi possono avere un valore predefinito di appena 4 kilobyte, mentre altri forniscono 2 megabyte. È possibile trovare la dimensione corrente utilizzando getsockopt() con SO_SNDBUF o SO_RCVBUF e impostarlo allo stesso modo utilizzando setsockopt(). Ma molti sistemi limitano la dimensione del buffer, a volte a importi arbitrariamente piccoli. Questo è tipicamente un valore del kernel come net.core.wmem_max o net.core.rmem_max, ma il riferimento esatto varia a seconda del sistema.

Si noti inoltre che setsockopt() può non riuscire anche se si richiede un importo inferiore al limite presunto. Quindi, per ottenere effettivamente la dimensione desiderata, è necessario chiamare ripetutamente lo setsockopt() utilizzando importi decrescenti fino a quando non riesce infine.

La pagina seguente è una nota tecnica della mia compagnia che tocca su questo argomento un po 'e fornisce i riferimenti per alcuni sistemi comuni: http://www.dataexpedition.com/support/notes/tn0024.html

+0

Buona risposta, grazie! – natli

0

Sembra a me come la classe UdpClient-Class offre un buffer per i dati ricevuti. Prova ad usare direttamente una presa. Si potrebbe anche voler impostare i socket ReceiveBufferSize a zero, anche se credo che sia usato solo per le connessioni TCP.

Problemi correlati