如何在C#中实现PsPing TCP ping

Ahm*_*gle 8 c# tcp ping

我正在尝试用C#实现Mark Russinovich的SysInternals PsPing工具来测量使用TCP ping的延迟.

我不确定它是如何进行ping调用的(显然不使用原始Window套接字,因为它不需要管理员权限来运行).我知道hping通过TCP发送SYN数据包并测量响应时间.

什么是准确测量服务器延迟的实现技术,而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
Run Code Online (Sandbox Code Playgroud)

更新:请不要回答"为什么你不使用Ping类,它已经做了",因为我问的是关于TCP的ping,而不是ICMP.

ziy*_*iya 20

我尝试了几种方法,首先想到我必须使用原始套接字或者至少使用本机调用,但是简单的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());
Run Code Online (Sandbox Code Playgroud)

使用Wireshark检查流量,我可以确认psping和上面的代码段正在创建完全相同的数据包序列.

-> [SYN]
<- [SYN,ACK]
-> [ACK]
-> [FIN,ACK]
<- [FIN,ACK]
-> [ACK]
Run Code Online (Sandbox Code Playgroud)

psping输出,没有预热并使用TCP ping:

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
Run Code Online (Sandbox Code Playgroud)

上述程序的输出:

C:\>TcpPing.exe stackoverflow.com 80
88.60ms
83.65ms
84.05ms
84.05ms
83.65 88.60 85.09
Run Code Online (Sandbox Code Playgroud)

至于测量,我必须说,有时在不同的跑步中会有不同的结果,但总的来说它们看起来非常接近:有点证明测量Connect()呼叫是足够好的.我在想,取几百个结果的中位数可能会更有信心.

  • EndPoint 类有点笨拙,所以我更喜欢使用 IPAddress 类并指定一个端口。要做到这一点: IPAddress ip = Dns.GetHostEntry("www.google.com.au").AddressList[0]; INT端口= 443;然后 sock.Connect(ip, port); (2认同)