2012-11-28 20 views
9

Desidero ottenere una velocità di download/upload accurata tramite un'interfaccia di rete utilizzando C# .NET So che può essere calcolato utilizzando GetIPv4Statistics().BytesReceived e interrompendo il thread per un po 'di tempo. Ma non sta dando l'output quello che sto ottenendo nel mio browser.Come ottenere una velocità di download/upload accurata in C# .NET?

+0

Quanto di una differenza è? Quale altro traffico di rete c'è? –

+0

Nella mia applicazione non vedo una velocità costante mentre il mio browser mostra qualcosa come la velocità costante. La mia domanda è molto fluttuante. –

+0

Come viene calcolato il throughput? Mi aspetterei che non fluttui molto. Ciò potrebbe indicare che la media mobile viene calcolata in modo errato. –

risposta

4

Guardando un'altra risposta a una domanda che hai postato in NetworkInterface.GetIPv4Statistics().BytesReceived - What does it return? credo che il problema potrebbe essere che si sta utilizzando a piccoli intervalli. Credo che il contatore contenga solo interi pacchetti e se per esempio stai scaricando un file i pacchetti potrebbero arrivare fino a 64 KB (65,535 bytes, dimensione del pacchetto IPv4 max), che è molto se il massimo throughput è 60 KB/s e stai misurando 200 ms intervalli.

Dato che la velocità è 60 KB/s, avrei impostato il tempo di esecuzione su 10 secondi per ottenere almeno 9 pacchetti per media. Se lo stai scrivendo per tutti i tipi di connessioni, ti consiglio di rendere la soluzione dinamica, ovvero se la velocità è elevata puoi facilmente ridurre l'intervallo di media, ma nel caso di connessioni lente devi aumentare l'intervallo di media.

O fare come @pst consiglia di avere una media mobile o semplicemente aumentare il sonno fino a forse 1 secondo.

E assicurarsi di dividere per il tempo effettivo impiegato anziché il tempo passato a Thread.Sleep().

pensiero Ulteriori intervalli

mio processo sarebbe qualcosa di simile, misurare per 5 secondi e raccogliere i dati, vale a dire byte ricevuto, così come il numero di pacchetti.

var timePerPacket = 5000/nrOfPackets; // Time per package in ms 
var intervalTime = Math.Max(d, Math.Pow(2,(Math.Log10(timePerPacket)))*100); 

Questo farà aumentare lentamente l'intervallo da alcune decine di ms al tempo per pacchetto. In questo modo otteniamo almeno (in media) un pacchetto per intervallo e non impazziremo se utilizziamo una connessione a 10 Gbps. La parte importante è che il tempo di misurazione non dovrebbe essere lineare rispetto alla quantità di dati ricevuti.

+0

Grazie. Sta dando l'output quasi corretto se aumento l'intervallo. Ma devo calcolare anche la velocità di altri NetworkInterfaces. Quindi, sarà troppo lento per aggiornare il valore di velocità di una particolare interfaccia di rete. Quindi, penso che dovrei andare per l'implementazione di @ pst. Cosa ne pensi? –

+1

@ soham.m17 Lo raccomando anche. E vedi la mia ultima modifica, più veloce è la connessione, minore è la "quantità di tempo" necessaria per il rapporto tra il throughput e la dimensione massima del pacchetto IPv4. Assicurati sempre di calcolare almeno una manciata di pacchetti :) – flindeberg

+0

Sembra improbabile che vengano utilizzati pacchetti ip> 15xx byte. Poche connessioni Internet supportano un MTU più grande. – CodesInChaos

3

Ecco un breve snippet di codice da LINQPad. Usa una media mobile molto semplice. Mostra "velocità accurate" usando "Speedtest.net". Le cose da tenere a mente sono Kbps in bit e i dati HTTP sono spesso compressi in modo che i "byte scaricati" siano significativamente più piccoli per dati altamente comprimibili. Inoltre, non dimenticare che in questi giorni qualsiasi vecchio processo potrebbe fare qualsiasi cosa vecchia su Internet (senza impostazioni del firewall più severe).

Mi piace la risposta di flindenberg (non modificare l'accettazione), e ho notato che alcuni periodi di polling restituiscono "0" in linea con le sue conclusioni.

Uso a proprio rischio e pericolo.

void Main() 
{ 
    var nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); 
    // Select desired NIC 
    var nic = nics.Single(n => n.Name == "Local Area Connection"); 
    var reads = Enumerable.Empty<double>(); 
    var sw = new Stopwatch(); 
    var lastBr = nic.GetIPv4Statistics().BytesReceived; 
    for (var i = 0; i < 1000; i++) { 

     sw.Restart(); 
     Thread.Sleep(100); 
     var elapsed = sw.Elapsed.TotalSeconds; 
     var br = nic.GetIPv4Statistics().BytesReceived; 

     var local = (br - lastBr)/elapsed; 
     lastBr = br; 

     // Keep last 20, ~2 seconds 
     reads = new [] { local }.Concat(reads).Take(20); 

     if (i % 10 == 0) { // ~1 second 
      var bSec = reads.Sum()/reads.Count(); 
      var kbs = (bSec * 8)/1024; 
      Console.WriteLine("Kb/s ~ " + kbs); 
     } 
    } 
} 
+0

Grazie. ma non ho la parte 'if (i% 10 == 0) {// ~ 1 second'. Stai visualizzando l'output ogni 1 s. è così? –

+0

@ soham.m17 Sì. È più facile da leggere di ogni 1/10 di secondo. In alternativa, basta sondare una volta al secondo e regolare la SMA per dire N (4 forse?) Secondi .. –

+0

Cosa intendi per SMA ?? –

5

Si prega di provare questo. Per verificare la velocità della connessione a Internet.

public double CheckInternetSpeed() 
{ 
     // Create Object Of WebClient 
     System.Net.WebClient wc = new System.Net.WebClient(); 

     //DateTime Variable To Store Download Start Time. 
     DateTime dt1 = DateTime.Now; 

     //Number Of Bytes Downloaded Are Stored In ‘data’ 
     byte[] data = wc.DownloadData("http://google.com"); 

     //DateTime Variable To Store Download End Time. 
     DateTime dt2 = DateTime.Now; 

     //To Calculate Speed in Kb Divide Value Of data by 1024 And Then by End Time Subtract Start Time To Know Download Per Second. 
     return Math.Round((data.Length/1024)/(dt2 - dt1).TotalSeconds, 2);    
    } 

Ti dà la velocità in Kb/Sec e condividi il risultato.

+0

Puoi provare questo. https://www.nuget.org/packages/InetSpeedWinRT/ –