PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/PingTracer/PingTracer.cs

https://github.com/kanosaki/PingTracer
C# | 150 lines | 127 code | 17 blank | 6 comment | 11 complexity | 593bb9d44157b27ac042cd5b993f1f7f MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net.NetworkInformation;
  6. using System.Threading.Tasks;
  7. using System.Threading;
  8. using System.Reactive;
  9. using System.Reactive.Subjects;
  10. using System.Reactive.Linq;
  11. using System.Reactive.Threading.Tasks;
  12. using System.Reactive.Concurrency;
  13. using System.Net;
  14. using System.Diagnostics;
  15. namespace PingTracer
  16. {
  17. public class Tracer : IDisposable
  18. {
  19. public IObservable<PingResult> PingReplies { get { return _pingReplies; } }
  20. public TimeSpan Interval { get; set; }
  21. public string TargetHost { get; set; }
  22. public int Ttl { get; set; }
  23. public bool Enabled { get; set; }
  24. /// <summary>
  25. /// ms
  26. /// </summary>
  27. public int PingTimeout { get; set; }
  28. Ping _ping;
  29. PingOptions _pingOptions;
  30. byte[] _data = BitConverter.GetBytes(1);
  31. IPAddress _target;
  32. Subject<PingResult> _pingReplies;
  33. IDisposable _workerSubscription;
  34. public Tracer(string target, int ttl, TimeSpan interval)
  35. {
  36. this.TargetHost = target;
  37. this.Ttl = ttl;
  38. this.Interval = interval;
  39. _pingReplies = new Subject<PingResult>();
  40. this.PingTimeout = 1000;
  41. this.Init();
  42. this.InitWorker();
  43. }
  44. private void InitWorker()
  45. {
  46. if (_workerSubscription != null)
  47. _workerSubscription.Dispose();
  48. _workerSubscription = Observable
  49. .Timer(dueTime: TimeSpan.Zero,
  50. period: this.Interval,
  51. scheduler: TaskPoolScheduler.Default)
  52. .Where(_ => this.Enabled)
  53. .Select(this.ExecPing)
  54. .Subscribe(_pingReplies.OnNext);
  55. }
  56. private void Init()
  57. {
  58. _ping = new Ping();
  59. _pingOptions = new PingOptions(this.Ttl, true);
  60. _target = Dns.GetHostEntry(this.TargetHost).AddressList.First();
  61. }
  62. protected PingResult ExecPing(long ping_count)
  63. {
  64. var sw = new Stopwatch();
  65. sw.Start();
  66. var result = new PingResult(_ping.Send(_target, this.PingTimeout, _data, _pingOptions));
  67. sw.Stop();
  68. result.InjectRoudTripTime(sw.Elapsed);
  69. return result;
  70. }
  71. public void Start()
  72. {
  73. this.Enabled = true;
  74. }
  75. public void Stop()
  76. {
  77. this.Enabled = false;
  78. }
  79. public void Dispose()
  80. {
  81. if (_workerSubscription != null)
  82. _workerSubscription.Dispose();
  83. }
  84. }
  85. /// <summary>
  86. /// Proxy class for PingReply
  87. /// </summary>
  88. public class PingResult
  89. {
  90. public PingResult(PingReply wrapped)
  91. {
  92. _wraped = wrapped;
  93. this.TimeStamp = DateTime.Now;
  94. }
  95. PingReply _wraped;
  96. TimeSpan _injectedTime;
  97. public double RoundtripTime
  98. {
  99. get { return this.CalcRoundTripTime(); }
  100. }
  101. public IPAddress Address { get { return _wraped.Address; } }
  102. public byte[] Buffer { get { return _wraped.Buffer; } }
  103. public IPStatus Status { get { return _wraped.Status; } }
  104. public PingOptions Options { get { return _wraped.Options; } }
  105. public DateTime TimeStamp { get; private set; }
  106. public void InjectRoudTripTime(TimeSpan time)
  107. {
  108. _injectedTime = time;
  109. }
  110. protected virtual double CalcRoundTripTime()
  111. {
  112. if (_wraped.Status == IPStatus.Success)
  113. {
  114. return _wraped.RoundtripTime;
  115. }
  116. else if (_wraped.Status == IPStatus.TtlExpired)
  117. {
  118. return _injectedTime.TotalMilliseconds;
  119. }
  120. else
  121. {
  122. if (_wraped.RoundtripTime == 0)
  123. {
  124. return _injectedTime.TotalMilliseconds;
  125. }
  126. else
  127. {
  128. return _wraped.RoundtripTime;
  129. }
  130. }
  131. }
  132. }
  133. }