using System;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
namespace Netch.Utils
{
public static class Ping
{
///
/// 缓存内容
///
private class CacheEntry
{
///
/// 缓存时间
///
public long Unix;
///
/// 延迟
///
public int Time;
}
///
/// 缓存表
///
private static Hashtable Cache = new Hashtable();
///
/// 测试 ICMP 延迟
///
///
///
private static int ICMPing(IPAddress addr)
{
using (var client = new System.Net.NetworkInformation.Ping())
{
var tk = client.SendPingAsync(addr);
if (!tk.Wait(1000))
{
return 999;
}
return Convert.ToInt32(tk.Result.RoundtripTime);
}
}
///
/// 测试 TCP 延迟
///
///
///
///
private static int TCPPing(IPAddress addr, ushort port)
{
using (var client = new TcpClient())
{
var sw = Stopwatch.StartNew();
var tk = client.ConnectAsync(addr, port);
if (!tk.Wait(1000))
{
sw.Stop();
return 999;
}
sw.Stop();
return Convert.ToInt32(sw.Elapsed.TotalMilliseconds);
}
}
///
/// 获取延迟
///
///
///
public static int Fetch(Models.Server.Server s)
{
/*
* -1 : Not Test
* -2 : DNS Exception
* -3 : Exception
* 999 : Timeout
*/
try
{
var addr = DNS.Fetch(s.Host);
if (addr == IPAddress.Any)
{
return -2;
}
if (Cache.Contains(addr))
{
var rule = Cache[addr] as CacheEntry;
if (DateTimeOffset.Now.ToUnixTimeSeconds() - rule.Unix < 30)
{
return rule.Time;
}
else
{
Cache.Remove(addr);
}
}
var time = 0;
if (Global.Config.Generic.ICMPing)
{
time = ICMPing(addr);
}
else
{
return TCPPing(addr, s.Port);
}
Cache.Add(addr, new CacheEntry() { Unix = DateTimeOffset.Now.ToUnixTimeSeconds(), Time = time });
return time;
}
catch (Exception e)
{
Global.Logger.Warning(e.ToString());
return -3;
}
}
}
}