2014-09-26 15 views
5

Próbuję zaimplementować SysInternals Marka Russinovicha PsPing tool w języku C#, aby zmierzyć opóźnienia przy użyciu ping TCP.Jak zaimplementować ping ping PsPing w C#

Nie jestem pewien, w jaki sposób wywołuje ping (najwyraźniej nie używa surowych gniazd Window, ponieważ nie wymaga uprawnień administratora do uruchomienia). Wiem, że hping wysyła pakiet SYN przez TCP i mierzy czas odpowiedzi.

Jaka byłaby technika wykonania dokładnego pomiaru opóźnień serwera, które przez TCP nie mierzy czasu ładowania strony, a jedynie opóźnienie sieci dla potwierdzenia odbioru? Czy istnieje biblioteka do tego?

C:\>psping stackoverflow.com:80 

PsPing v2.01 - PsPing - ping, latency, bandwidth measurement utility 
Copyright (C) 2012-2014 Mark Russinovich 
Sysinternals - www.sysinternals.com 

Pinging 198.252.206.16 with 32 bytes of data: 
5 iterations (warmup 1) ping test: 
Reply from 198.252.206.16: 81.57ms 
Reply from 198.252.206.16: 80.81ms 
Reply from 198.252.206.16: 80.68ms 
Reply from 198.252.206.16: 80.52ms 
Reply from 198.252.206.16: 80.71ms 

Ping statistics for 198.252.206.16: 
    Sent = 4, Received = 4, Lost = 0 (0% loss), 
    Minimum = 80.52ms, Maximum = 80.81ms, Average = 80.68ms 

Aktualizacja: Proszę nie odpowiedzieć jak „dlaczego nie można użyć klasy Ping, to już robi coś”, jak pytam o ping przez TCP, ICMP nie.

+1

Wiele narzędzi Sysinternals korzysta z nieudokumentowanych wywołań systemowych. Jest mało prawdopodobne, aby znaleźć łatwe do odniesienia źródło mówiąc, jak to robi, nie mówiąc o tym, jak zrobić to samo z C#. –

+0

@ScottChamberlain po prostu wypróbowując może istnieje metoda, o której nie wiem. –

+0

@ahmetalpbalkan: co z klasą Ping, która umożliwia pingowanie serwera lub wewnętrznego adresu IP i można uzyskać powtórkę Time? http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ping%28v=vs.110%29.aspx – houssam

Odpowiedz

14

Próbowałem kilka podejść, najpierw myślenie musiałem użyć gniazd surowych lub przynajmniej używać połączeń rodzimych, ale prosty TCP połączyć i blisko zdaje się tworzyć dokładnie takie same wyniki jak psping narzędzie:

var times = new List<double>(); 
for (int i = 0; i < 4; i++) 
{ 
    var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    sock.Blocking = true; 

    var stopwatch = new Stopwatch(); 

    // Measure the Connect call only 
    stopwatch.Start(); 
    sock.Connect(endPoint); 
    stopwatch.Stop(); 

    double t = stopwatch.Elapsed.TotalMilliseconds; 
    Console.WriteLine("{0:0.00}ms", t); 
    times.Add(t); 

    sock.Close(); 

    Thread.Sleep(1000); 
} 
Console.WriteLine("{0:0.00} {1:0.00} {2:0.00}", times.Min(), times.Max(), times.Average()); 

Kontrola ruchu z wykorzystaniem Wiresharka, można potwierdzić zarówno psping i fragment powyżej tworzenie dokładnie tę samą sekwencję pakietów.

-> [SYN] 
<- [SYN,ACK] 
-> [ACK] 
-> [FIN,ACK] 
<- [FIN,ACK] 
-> [ACK] 

Wyjście z psping bez rozgrzewki i za pomocą polecenia ping TCP:

C:\>psping -w 0 stackoverflow.com:80 

PsPing v2.01 - PsPing - ping, latency, bandwidth measurement utility 
Copyright (C) 2012-2014 Mark Russinovich 
Sysinternals - www.sysinternals.com 

TCP connect to 198.252.206.16:80: 
4 iterations (warmup 0) connecting test: 
Connecting to 198.252.206.16:80: 92.30ms 
Connecting to 198.252.206.16:80: 83.16ms 
Connecting to 198.252.206.16:80: 83.29ms 
Connecting to 198.252.206.16:80: 82.98ms 

TCP connect statistics for 198.252.206.16:80: 
    Sent = 4, Received = 4, Lost = 0 (0% loss), 
    Minimum = 82.98ms, Maximum = 92.30ms, Average = 85.43ms 

Wyjście z programu powyżej:

C:\>TcpPing.exe stackoverflow.com 80 
88.60ms 
83.65ms 
84.05ms 
84.05ms 
83.65 88.60 85.09 

jak dla pomiarów, muszę powiedzieć, czasami są całkiem różne wyniki na różnych biegach, ale ogólnie wydawało się, że są całkiem blisko: rodzaj udowadnia, że ​​mierzenie wywołania jest wystarczająco dobre. Myślę, że przyjęcie mediana kilkuset wyników może udowodnić to z nieco większą pewnością.

+1

Wyszło mi bardzo dobrze! Odzwierciedla również bardzo bliskie wyniki dla 'psping'. Dziękuję bardzo, zasłużone. –

+0

Klasa EndPoint jest trochę nieporęczna, więc wolę używać klasy IPAddress i określać port. Aby to zrobić: IPAddress ip = Dns.GetHostEntry ("www.google.com.au"). AddressList [0]; int port = 443; a następnie sock.Connect (ip, port); –

1

Winsock z pewnością pozwoli ci to łatwo zrobić.

Czy spojrzałeś na źródło programów takich jak http://www.elifulkerson.com/projects/tcping.php?

Dość prostego programu (konsola), który robi dokładnie to, co chcesz (AFAIK), i dostarczany z kodem źródłowym, który wygląda na bardzo przejrzysty, krótki i łatwy do odczytania (nawet dla programistów spoza C++, nie ćwiczyłem C++ od jakiegoś czasu i mimo to bardzo miło było go przeczytać).

Możesz go zbudować i debugować za pomocą VS, aby szybko znaleźć to, co chcesz. Powinno być łatwo dotrzeć do kilku wywołań Win32 API związanych z TCP Ping. W ten sposób z łatwością można przekonwertować interesującą część na C# lub osadzić ją w zarządzanej bibliotece DLL.

Po prostu przetestuj wcześniej, czy robi dokładnie to, co chcesz.

Link

Źródło: http://www.elifulkerson.com/projects/downloads/tcping-0.23/tcping-src.zip

Powiązane problemy