2014-09-26 6 views
5

Я пытаюсь реализовать SysInternals Марка Руссиновича PsPing tool в C# для измерения задержек с использованием TCP-пинга.Как реализовать PSPing TCP ping в C#

Я не уверен, как он выполняет вызов ping (видимо, не использует raw-сокеты Windows, поскольку для него не требуются привилегии администратора). Я знаю, что hping отправляет пакет SYN через TCP и измеряет время отклика.

Какова была бы методика реализации точного измерения задержки сервера, которая по TCP не измеряет время загрузки страницы, а только время ожидания сети для подтверждения пакета? Есть ли библиотека для этого?

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 

Обновление: Пожалуйста, не отвечайте, как «почему бы вам не использовать класс Ping, это уже делает вещь», как я и спрашиваю о пинг через TCP, а не ICMP.

+1

Многие инструменты Sysinternals используют недокументированные системные вызовы. Вы вряд ли найдете простой источник ссылок, говорящий, как он это делает, не говоря уже о том, как сделать то же самое с C#. –

+0

@ScottChamberlain просто пытается, возможно, есть метод, о котором я не знаю. –

+0

@ahmetalpbalkan: как насчет класса Ping, который позволяет вам пинговать сервер или внутренний IP-адрес, и вы можете получить время воспроизведения? http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ping%28v=vs.110%29.aspx – houssam

ответ

14

Я попробовал несколько подходов, первый думая, что я должен был использовать сырые сокеты или по крайней мере использовать собственные вызовы, но простой TCP подключения и близко, кажется, создает точно такие же результаты, что и psping утилиты:

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()); 

Проверка трафика с помощью Wireshark, я могу подтвердить, как psping и фрагмент кода выше, создавая точно такой же последовательности пакетов.

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

Выхода из psping, без разминки и использования 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 

выхода из программы выше:

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

Что касается измерений, я должен сказать, что иногда довольно много разных результатов на разных трассах, но в целом они казались довольно близкими: вид доказывает, что звонок Connect() достаточно хорош. Я думаю, что медиана нескольких сотен результатов может доказать это с немного большей уверенностью.

+1

Работал очень хорошо для меня! Он также отражает очень близкие результаты к 'psping'. Большое вам спасибо, заслуженный. –

+0

Класс EndPoint немного громоздкий, поэтому я предпочитаю использовать класс IPAddress и указать порт. Для этого: IPAddress ip = Dns.GetHostEntry ("www.google.com.au"). AddressList [0]; int port = 443; а затем sock.Connect (ip, порт); –

1

Winsock, безусловно, позволит вам сделать это легко.

Вы смотрели источник таких программ, как http://www.elifulkerson.com/projects/tcping.php?

Довольно простая программа (консоль), которая делает именно то, что вы хотите (AFAIK), и снабжена исходным кодом, который выглядит очень четким, коротким и легким для чтения (даже для программистов, не использующих C++, я не практиковал C++, и, несмотря на это, мне было очень приятно читать).

Вы можете построить его и отладить его с помощью VS, чтобы быстро найти то, что вы хотите. Должно быть легко получить там несколько вызовов API Win32, задействованных в TCP Ping. Таким образом, вы можете легко преобразовать интересную часть в C# или вставить ее в управляемую DLL.

Просто проверьте, если он делает именно то, что вы хотите.

Источник ссылка: http://www.elifulkerson.com/projects/downloads/tcping-0.23/tcping-src.zip

Смежные вопросы