using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Timers; using System.Xml.Linq; namespace Vrh.Log4Pro.MaintenanceConsole.ToolsNS { /// /// A pinger objektum ping ciklusokat indít (egy ping ciklusban több ping kérés van/lehet), és ezek eredményét /// tárolja tömörített formátumban elsősorban abból a célból, hogy a tárolt adatok alapján trend diagramot lehessen /// készíteni a kapcsolat minőségének kimutatására. /// public class Pinger : IDisposable { /// /// Egy Pinger objektum létrehozása xml-ből /// /// a ping célállomása /// a pinger konfigurációs paramétereit tartalmazó xml struktúra public Pinger(string hostNameOrAddress, XElement pingerconfig) : this(hostNameOrAddress, new PingerConfig(pingerconfig)) { } /// /// Egy Pinger objektum létrehozása PrinterConfig osztályból /// /// a ping célállomása /// a konfigurációt tartalmazó pinger objektum private Pinger(string hostNameOrAddress, PingerConfig pc) { this.HostNameOrAddress = hostNameOrAddress; this.History = new PingHistory(hostNameOrAddress, pc.pingerhistorylength, pc.pingcyclefrequency); this.PingTimeout = pc.pingtimeout; this.PingCycleFrequency = pc.pingcyclefrequency; this.PingCycleNumberOfPackages = pc.pingcyclenumofpackages; this.PingerActiveLength = pc.pingeractivlength; this.Configuration = pc; } /// /// A pinger indítása/újraindítása; elindítja a ping ciklus időzítőt, és elkezdi/folytatja a ping státusz adatok letárolását /// /// pinger konfig xml struktúra, amely /// (jellemzően újraindítás esetén) a Pinger részleges átkonfigurálását teszi lehetővé public void Start(XElement pingerconfig = null) { lock (pingcyclelocker) { CycleTimerStop(); Reconfigure(pingerconfig); CycleTimerStart(); if (this.PingerActiveLength > 0) { AutoStopTimerStop(); AutoStopTimerStart(); } } } /// /// A pinger leállítása; kikapcsolja a ping ciklus időzítőt, és leállítja a ping státusz adatok letárolását /// public void Stop() { CycleTimerStop(); } /// /// A Pinge objektum átkonfigurálás a a megadott xml struktúra alapján /// /// private void Reconfigure(XElement pingerconfig = null) { lock (pingcyclelocker) { if (pingerconfig != null) { var pc = new PingerConfig(pingerconfig); this.PingTimeout = pc.pingtimeout; this.PingCycleFrequency = pc.pingcyclefrequency; this.PingCycleNumberOfPackages = pc.pingcyclenumofpackages; this.PingerActiveLength = pc.pingeractivlength; this.History.SetHistoryLength(pc.pingerhistorylength); } } } /// /// A pinger autostop lejártakor végrehajtandó metódus /// /// /// private void AutoStop(Object source, ElapsedEventArgs e) { CycleTimerStop(); } private void CycleTimerStop() { lock (pingcyclelocker) { if (this.CycleTimer != null) { this.CycleTimer.Enabled = false; } this.Operating = false; } } private void CycleTimerStart() { lock (pingcyclelocker) { if (this.CycleTimer == null) { this.CycleTimer = new System.Timers.Timer(); this.CycleTimer.Elapsed += StartPingCycle; this.CycleTimer.AutoReset = true; } this.CycleTimer.Interval = this.PingCycleFrequency; this.CycleTimer.Enabled = true; this.Operating = true; } } private void AutoStopTimerStop() { lock (pingcyclelocker) { if (this.AutoStopTimer != null) { this.AutoStopTimer.Enabled = false; } } } private void AutoStopTimerStart() { lock (pingcyclelocker) { if (this.AutoStopTimer == null) { this.AutoStopTimer = new System.Timers.Timer(); this.AutoStopTimer.Elapsed += AutoStop; this.AutoStopTimer.AutoReset = false; } this.AutoStopTimer.Interval = this.PingerActiveLength; this.AutoStopTimer.Enabled = true; } } /// /// Dispose /// public void Dispose() { Stop(); if (this.CycleTimer != null) { this.CycleTimer.Dispose(); this.CycleTimer = null; } if (this.AutoStopTimer != null) { this.AutoStopTimer.Dispose(); this.AutoStopTimer = null; } this.History.Dispose(); } /// /// Visszadja a history listát /// /// public Pinger.PingHistory GetHistory() { lock (pingcyclelocker) { this.History.PingerState = this.CycleTimer != null && this.CycleTimer.Enabled ? PingerStatus.Operating : PingerStatus.Still; return this.History; } } #region public fields /// /// A ping célállomása /// public string HostNameOrAddress; /// /// true: a pingcycle timer működik, a pingelés folyamataos /// false: a pingcycle timer NEM működik, a pingelés áll /// public bool Operating; /// /// Egy ciklusban kiadott ping kérések száma. /// public PingerConfig Configuration; #endregion public fields #region private metódusok /// /// A ping ciklus időzítés lejártakor elindított metódus, ami végrehajt egy ping ciklust és eredményét bedolgozza a PingStateQueue sorba /// /// /// private void StartPingCycle(Object source, ElapsedEventArgs e) { lock (pingcyclelocker) { this.CycleTimer.Enabled = false; // kikapcsoljuk a timer-t a ciklus végrehajtása alatt var newpc = new PingCycle(this.HostNameOrAddress, this.PingCycleNumberOfPackages, this.PingTimeout).Execute(); this.History.Merge(newpc); this.CycleTimer.Interval = this.PingCycleFrequency;// ha esetleg közben újrakonfigurálták.... this.CycleTimer.Enabled = true; // a ciklus végrehajtása után ismét elindítjuk az időzítőt } } #endregion private metódusok #region private fields /// /// Az egyes ping kérések maximális timeout-ja (millisecundum) /// private int PingTimeout; /// /// A ping ciklus befejeződése után ennyi idővel indítja a következőt (másodpercben) /// private int PingCycleFrequency; /// /// A ping vizsgálat teljes időtartama; Ennyi idő eltelte után nem indít több több ping ciklust. /// Érték percben. Ha az érték 0, akkor végtelen hosszú időn keresztül indít ping ciklusokat. /// private int PingerActiveLength; /// /// Egy ciklusban kiadott ping kérések száma. /// private int PingCycleNumberOfPackages; /// /// A ping ciklusok keveredését megakadályozó locker objektum /// private object pingcyclelocker = new object(); /// /// A Pinger működési periódusának hossza (az autostop timer kikapcsolási ideje) (perc) /// private System.Timers.Timer AutoStopTimer; /// /// A Ping ciklus timere /// private System.Timers.Timer CycleTimer; /// /// Ping history /// private PingHistory History; #endregion private fields #region PingerConfig class /// /// PingerConfig osztály /// public class PingerConfig { /// /// példány létrehozása xml struktúra alapján /// /// public PingerConfig(XElement pingerconfig) { if (pingerconfig != null) { var _pingtimeout = GetPositiveIntFromXml(PINGTIMEOUT, pingerconfig, DEFAULT_PINGTIMEOUT); var _pingcyclefrequency = GetPositiveIntFromXml(PINGCYCLEFREQUENCY, pingerconfig, 0); var _pingcyclenumofpackages = GetPositiveIntFromXml(PINGCYCLENUMOFPACKAGES, pingerconfig, DEFAULT_PINGCYCLENUMOFPACKAGES); var _pingeractivlength = GetPositiveIntFromXml(PINGERACTIVELENGTHTOSTOPPERIOD, pingerconfig, DEFAULT_PINGERACTIVELENGTH); var _pingerhistorylength = GetPositiveIntFromXml(PINGERHISTORYLENGTH, pingerconfig, DEFAULT_PINGERHISTORYLENGTH); SetValues(_pingtimeout, _pingcyclefrequency, _pingcyclenumofpackages, _pingeractivlength, _pingerhistorylength); } else { SetValues(); } } /// /// Példány létrehozása paraméterek alapján; a konstruktor célja a mértékegységek és a default értékek kezelése /// /// millisecond /// seconds /// pcs /// minutes /// minutes public PingerConfig(int pingtimeout = 0, int pingcyclefrequency = 0, int pingcyclenumofpackages = 0, int pingeractivelength = 0, int pingerhistorylength = 0) { SetValues(pingtimeout, pingcyclefrequency, pingcyclenumofpackages, pingeractivelength, pingerhistorylength); } /// /// Beállítja a field-ek értékét a megfelelő mértékegységben a paraméterek, illetve az alapértelmezések szerint /// /// millisecond /// seconds /// pcs /// minutes /// minutes private void SetValues(int pingtimeout = 0, int pingcyclefrequency = 0, int pingcyclenumofpackages = 0, int pingeractivelength = 0, int pingerhistorylength = 0) { this.pingtimeout = pingtimeout <= 0 ? PingerConfig.DEFAULT_PINGTIMEOUT : pingtimeout; this.pingcyclefrequency = pingcyclefrequency * 1000; if (this.pingcyclefrequency < this.pingtimeout) { this.pingcyclefrequency = this.pingtimeout; } this.pingcyclenumofpackages = pingcyclenumofpackages <= 0 ? PingerConfig.DEFAULT_PINGCYCLENUMOFPACKAGES : pingcyclenumofpackages; this.pingeractivlength = (pingeractivelength <= 0 ? PingerConfig.DEFAULT_PINGERACTIVELENGTH : pingeractivelength) * 60 * 1000; this.pingerhistorylength = (pingerhistorylength <= 0 ? PingerConfig.DEFAULT_PINGERHISTORYLENGTH : pingerhistorylength) * 60 * 1000; } /// /// Egy int értéket kiemel a megadott xml struktúrából, ha nincs ott a keresett érték, /// vagy nem integer, vagy nem pozitív, akkor az alapértelmezést adja vissza /// /// az xml struktúrában a keresett elem neve /// az xml struktúra /// az alapértelmezett érték /// private static int GetPositiveIntFromXml(string xname, XElement pingerconfig, int defaultvalue) { string valstr = pingerconfig?.Element(XName.Get(xname))?.Value; int val = defaultvalue; if (valstr != null && int.TryParse(valstr, out int val1) && val1 > 0) { val = val1; } return val; } public int pingtimeout; public int pingcyclefrequency; public int pingcyclenumofpackages; public int pingeractivlength; public int pingerhistorylength; const string PINGTIMEOUT = "PingTimeout"; const string PINGCYCLEFREQUENCY = "PingCycleFrequency"; const string PINGCYCLENUMOFPACKAGES = "PingCycleNumOfPackages"; const string PINGERACTIVELENGTHTOSTOPPERIOD = "PingerActiveLength"; const string PINGERHISTORYLENGTH = "PingerHistoryLength"; public const int DEFAULT_PINGTIMEOUT = PingCycle.MAXROUNDTRIPTIMEOUTCATEGORY; public const int DEFAULT_PINGCYCLENUMOFPACKAGES = 4; public const int DEFAULT_PINGERACTIVELENGTH = 60; public const int DEFAULT_PINGERHISTORYLENGTH = 60; } #endregion PingerConfig class #region PingHistory class /// /// Ping history struktúra /// public class PingHistory : IDisposable { /// /// Ping állapot-sor. Minden eleme egy kezdő-időponttól fogva a következő elem kezdőidopontjáig fennálló állapotot ír le. /// Ha az új státusz állapot-ban a RoundtripTimeCategory vagy StatusCategory értéke a sorban levő legutolsó elemben levő értékekhez képes /// KÜLÖNBÖZIK, akkor Új elem kerül be a sorba; /// AZONOS, akkor a legutolsó elemben a PackagesSent és PackagesLost értékekhez hozzáadódik az új elemben levő megfelelő érték, de új elem nem kerül hozzáadásra /// public List PingStateQueue; /// /// A PingStateQueue utolsó eleme /// private PingCycle LastPingCycle; /// /// A tárolt history hossza percben /// public int Length; /// /// A ping ciklusok gyakorisága /// public int PingCycleFrequency; public string HostNameOrAddress; public PingerStatus PingerState = PingerStatus.Still; public DateTime StartTime; private object historylocker = new object(); public PingHistory(string hostnameoraddress, int pingerhistorylength,int pingcyclefrequency) { this.HostNameOrAddress = hostnameoraddress; this.PingStateQueue = new List(); this.LastPingCycle = null; this.Length = pingerhistorylength; this.PingCycleFrequency = pingcyclefrequency; } public PingHistory(PingHistory ph) { this.HostNameOrAddress = ph.HostNameOrAddress; this.PingStateQueue = ph.PingStateQueue.Select(x=>new PingCycle(x)).ToList(); this.LastPingCycle = ph.LastPingCycle; this.Length = ph.Length; this.PingCycleFrequency = ph.PingCycleFrequency; } public void Dispose() { this.PingStateQueue = null; this.LastPingCycle = null; } /// /// A PrintCycle beillesztése a sor végére, vagy "hozzáadása" az utolsó elemhez /// /// public void Merge(PingCycle newpc) { lock (historylocker) { if (this.LastPingCycle?.isDifferent(newpc) ?? true) { this.PingStateQueue.Add(newpc); this.LastPingCycle = newpc; } else { var totalrtt = ((this.LastPingCycle.RoundtripTimeAverage * this.LastPingCycle.NumberOfCycles) + newpc.RoundtripTimeAverage); this.LastPingCycle.NumberOfCycles++; this.LastPingCycle.RoundtripTimeAverage = totalrtt / this.LastPingCycle.NumberOfCycles; this.LastPingCycle.PackagesSent += newpc.PackagesSent; this.LastPingCycle.PackagesLost += newpc.PackagesLost; this.LastPingCycle.LastTimestamp = newpc.StartTimestamp; if (newpc.RoundtripTimeMax != -1 && this.LastPingCycle.RoundtripTimeMax != -1) { if (this.LastPingCycle.RoundtripTimeMax < newpc.RoundtripTimeMax) { this.LastPingCycle.RoundtripTimeMax = newpc.RoundtripTimeMax; } if (this.LastPingCycle.RoundtripTimeMin > newpc.RoundtripTimeMin) { this.LastPingCycle.RoundtripTimeMin = newpc.RoundtripTimeMin; } } } var borderts = newpc.StartTimestamp.AddMilliseconds(-1 * this.Length); this.PingStateQueue.RemoveAll(x => x.LastTimestamp <= borderts); var firstelement = this.PingStateQueue.FirstOrDefault(); if (firstelement != null && firstelement.StartTimestamp < borderts) { var partiallength = (firstelement.LastTimestamp - borderts).TotalMilliseconds; var fulllength = (firstelement.LastTimestamp - firstelement.StartTimestamp).TotalMilliseconds; firstelement.PackagesSent = (int)((double)firstelement.PackagesSent * partiallength / fulllength); firstelement.PackagesLost = (int)((double)firstelement.PackagesLost * partiallength / fulllength); firstelement.NumberOfCycles = (int)((double)firstelement.NumberOfCycles * partiallength / fulllength); if (firstelement.NumberOfCycles == 0 || firstelement.PackagesSent == 0) { this.PingStateQueue.Remove(firstelement); firstelement = this.PingStateQueue.FirstOrDefault(); } var packagelostratio = firstelement.PackagesLost / firstelement.PackagesSent; firstelement.PackagesSentCategory = packagelostratio == 0 ? PingCycle.LostPackageCategory.Excellent : packagelostratio < 0.1 ? PingCycle.LostPackageCategory.Good : packagelostratio < 0.3 ? PingCycle.LostPackageCategory.Acceptable : PingCycle.LostPackageCategory.Bad; firstelement.StartTimestamp = borderts; } StartTime = firstelement?.StartTimestamp ?? DateTime.MaxValue; } } /// /// Beállítja a history hosszát /// /// public void SetHistoryLength(int pingerhistoryperiod) { lock (historylocker) { this.Length = pingerhistoryperiod; } } } #endregion PingHistory class #region PingCycle class /// /// A ping history-ban szereplő elemek típusa /// public class PingCycle { /// /// Ping ciklus objektum létrehozása /// /// a pingek célja /// ennyi ping-et kell végrehajtani /// ennyi az egyes ping-ek timeout-ja public PingCycle(string hostnameoraddress, int numofpings, int pingtimeout) { this.HostNameOrAddress = hostnameoraddress; this.PackagesSent = numofpings; this.PingTimeout = pingtimeout; this.PackagesLost = 0; this.PackagesSentCategory = LostPackageCategory.Excellent; this.NumberOfCycles = 1; this.StatusCategory = IPStatusCategory.NotExecuted; this.RoundtripTimeAverage = 0; this.RoundtripTimeMin = -1; this.RoundtripTimeMax = -1; } public PingCycle(PingCycle pc) { this.HostNameOrAddress = pc.HostNameOrAddress; this.PackagesSent = pc.PackagesSent; this.PingTimeout = pc.PingTimeout; this.PackagesLost = pc.PackagesLost; this.PackagesSentCategory = pc.PackagesSentCategory; this.NumberOfCycles = pc.NumberOfCycles; this.StatusCategory = pc.StatusCategory; this.RoundtripTimeAverage = pc.RoundtripTimeAverage; this.RoundtripTimeMax = pc.RoundtripTimeMax; this.RoundtripTimeMin= pc.RoundtripTimeMin; } #region public fields,enums /// /// A maximális ping timeout kategória értéke /// public const int MAXROUNDTRIPTIMEOUTCATEGORY = 5000; /// /// A Ping állapot ezen időpillanattól kezdődően állt/áll fenn /// public DateTime StartTimestamp; /// /// A Ping állapot ezen időpillanattól kezdődően állt/áll fenn /// public DateTime LastTimestamp; /// /// Az állapot ilyen válaszidőt jelent (valójában ez is egy kategória, de egy konkrét idő érték jellemzi) /// public int RoundtripTime; /// /// A ping ciklusban végrehajtott ping-ek maximális válaszideje /// public int RoundtripTimeMax=-1; /// /// A ping ciklusban végrehajtott ping-ek minimális válaszideje /// public int RoundtripTimeMin=-1; /// /// A pontos válaszidők átlaga /// public int RoundtripTimeAverage; /// /// Az állapot ilyen válaszidő kategóriát jelent /// public RoundTripTimeCategory RoundtripTimeCategory; /// /// Az állapot ilyen IPStatus kategóriát jelent /// public IPStatusCategory StatusCategory; /// /// Ebben a státus állapotban ennyi csomag került kiküldésre /// public int PackagesSent; /// /// Ebben a státus állapotban ennyi csomag veszett el nem Success /// public int PackagesLost; /// /// Ebben a státus állapotban az elveszett csomagokra utaló státusz /// public LostPackageCategory PackagesSentCategory; /// /// A ping ciklusok száma ebben az egységben /// public int NumberOfCycles; /// /// Válasz státusz kategóriák; minél nagyobb az érték, annál kevesebbet tudunk a hiba okáról. /// public enum IPStatusCategory { Success = 0, TimedOut = 10, PortUnreachable = 20, HostUnreachable = 30, NetworkUnreachable = 40, Failed = 50, NotExecuted = 100, } public enum LostPackageCategory { Excellent = 0, Good = 1, Acceptable = 2, Bad = 3, } public enum RoundTripTimeCategory { Q1 = 0, Q2 = 1, Q3 = 2, Q4 = 3, } #endregion public fields,enums #region isDifferent /// /// Eldönti, hogy a két objektum azonosnak tekinthető-e, vagy sem /// /// /// public bool isDifferent(PingCycle pc) { return this.StatusCategory != pc.StatusCategory || this.RoundtripTime != pc.RoundtripTime; } #endregion isDifferent #region Execute /// /// Egy ping ciklus végrehajtása; /// /// /// StatusCategory: értéke NotExecuted értéktől különbözni fog. /// StartTimestamp: értéke a hívás időpillanata lesz. /// PackagesLost: a nem Success-sel visszatérő ping-ek száma /// RoundtripTimeCategory: a válaszidő kategória értéke /// public PingCycle Execute() { this.StartTimestamp = DateTime.Now; this.LastTimestamp = this.StartTimestamp; for (var i = 0; i < this.PackagesSent; i++) { var pr = PingTool.Ping(this.HostNameOrAddress, (int)PingTimeout);//egy ping kérés feladása AddResponse(pr, i + 1);//a ping válasz "bedolgozása" a pingciklus-állapotba } this.RoundtripTime = RoundTripTimeLimits.LastOrDefault(x => x <= this.RoundtripTimeAverage); var RoundTripTimeyCategoryValue = RoundTripTimeyCategoryLimits.LastOrDefault(x => x < this.RoundtripTimeAverage); var RoundTripTimeyCategoryIndex = RoundTripTimeyCategoryLimits.FindIndex(x => x == RoundTripTimeyCategoryValue); this.RoundtripTimeCategory = RoundTripTimeyCategoryIndex == 0 ? RoundTripTimeCategory.Q1 : RoundTripTimeyCategoryIndex == 1 ? RoundTripTimeCategory.Q2 : RoundTripTimeyCategoryIndex == 2 ? RoundTripTimeCategory.Q3 : RoundTripTimeCategory.Q4; return this; } #endregion Execute #region private elemek /// /// a ping célcíme /// private string HostNameOrAddress; /// /// A FINOM válaszidő kategóriákat tartalmazza; egy válasz az i. válaszidő kategóriába tartozik, ha a pontos válaszidő nagyobb, vagy egyenlő, /// mint az i. elem értéke, de kisebb, mint az i+1. elem értéke.A sor első elemének értéke mindig 0!!!! /// Ha a sor értékei: 0:0,1:100,2:200,3:300,4:400,5:500, a pontos válaszidő 350, akkor ez a 2. kategóriába tartozik, ha pontos válaszidő. /// private static List RoundTripTimeLimits = new List { 0, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, 1000, 1250, 1500, 1750, 2000, 2500, 3000, 3500, 4000, 4500, PingCycle.MAXROUNDTRIPTIMEOUTCATEGORY, }; /// /// A DURVA válaszidő kategóriákat tartalmazza; egy válasz az i. válaszidő kategóriába tartozik, ha a pontos válaszidő nagyobb, vagy egyenlő, /// mint az i. elem értéke, de kisebb, mint az i+1. elem értéke.A sor első elemének értéke mindig 0!!!! /// Ha a sor értékei: 0:0,1:100,2:200,3:300,4:400,5:500, a pontos válaszidő 350, akkor ez a 2. kategóriába tartozik, ha pontos válaszidő. /// private static List RoundTripTimeyCategoryLimits = new List { 0, 50, 250, 750, }; /// /// Az egyes ping kérések timeout-ja /// private int PingTimeout; /// /// A ping válasz bedolgozása a pingciklus státuszba /// /// a ping válasza /// a ping kérés indexe; 1,2,.... private void AddResponse(PingReply pr, int i) { var ipsCat = GetIPStatusCategory(pr); if (ipsCat==IPStatusCategory.Success) { int prroundtriptime = pr.RoundtripTime >= int.MaxValue ? int.MaxValue : (int)pr.RoundtripTime; this.RoundtripTimeMin = prroundtriptime < this.RoundtripTimeMin || this.RoundtripTimeMin ==-1 ? prroundtriptime : this.RoundtripTimeMin; this.RoundtripTimeMax = prroundtriptime > this.RoundtripTimeMax || this.RoundtripTimeMax == -1 ? prroundtriptime : this.RoundtripTimeMax; this.RoundtripTimeAverage = ((i - 1) * this.RoundtripTimeAverage + prroundtriptime) / i;// az átlagos válaszidőt tárolja } else { this.PackagesLost++; } if (ipsCat < this.StatusCategory) { this.StatusCategory = ipsCat; }// a legjobb státuszt tárolja } /// /// Visszaadja, hogy a PingReply adat alapján a válasz melyik státusz kategóriába tartozik /// /// /// private IPStatusCategory GetIPStatusCategory(PingReply pr) { switch (pr.Status) { case IPStatus.Success: return IPStatusCategory.Success;//Success = 0,The ICMP echo request succeeded; an ICMP echo reply was received. When you get this status code, the other System.Net.NetworkInformation.PingReply properties contain valid data. case IPStatus.DestinationNetworkUnreachable: //DestinationNetworkUnreachable = 11002,The ICMP echo request failed because the network that contains the destination computer is not reachable. return IPStatusCategory.NetworkUnreachable; case IPStatus.BadRoute: //BadRoute = 11012,The ICMP echo request failed because there is no valid route between the source and destination computers. case IPStatus.DestinationUnreachable: //DestinationUnreachable = 11040,The ICMP echo request failed because the destination computer that is specified in an ICMP echo message is not reachable; the exact cause of problem is unknown. case IPStatus.DestinationHostUnreachable: //DestinationHostUnreachable = 11003,The ICMP echo request failed because the destination computer is not reachable. return IPStatusCategory.HostUnreachable; case IPStatus.TtlReassemblyTimeExceeded://TtlReassemblyTimeExceeded = 11014,The ICMP echo request failed because the packet was divided into fragments for transmission and all of the fragments were not received within the time allottedfor reassembly. RFC 2460 (available at www.ietf.org) specifies 60 seconds as the time limit within which all packet fragments must be received. case IPStatus.TtlExpired://TtlExpired = 11013,The ICMP echo request failed because its Time to Live (TTL) value reached zero, causing the forwarding node (router or gateway) to discard the packet. case IPStatus.TimeExceeded: //TimeExceeded = 11041,The ICMP echo request failed because its Time to Live (TTL) value reached zero, causing the forwarding node (router or gateway) to discard the packet. case IPStatus.TimedOut: //TimedOut = 11010,The ICMP echo Reply was not received within the allotted time. The default time allowed for replies is 5 seconds. You can change this value using theOverload:System.Net.NetworkInformation.Ping.Send or Overload:System.Net.NetworkInformation.Ping.SendAsync methods that take a timeout parameter. return IPStatusCategory.TimedOut; //DestinationProhibited = 11004,The ICMPv6 echo request failed because contact with the destination computer is administratively prohibited. This value applies only to IPv6. case IPStatus.DestinationProtocolUnreachable://DestinationProtocolUnreachable = 11004, The ICMP echo request failed because the destination computer that is specified in an ICMP echo message is not reachable, because it does not support the packet'sprotocol. This value applies only to IPv4. This value is described in IETF RFC 1812 as Communication Administratively Prohibited. case IPStatus.DestinationPortUnreachable: //DestinationPortUnreachable = 11005,Summary: The ICMP echo request failed because the port on the destination computer is not available. case IPStatus.Unknown://Unknown = -1,The ICMP echo request failed for an unknown reason. case IPStatus.NoResources: //NoResources = 11006,Summary: The ICMP echo request failed because of insufficient network resources. case IPStatus.BadOption: //BadOption = 11007,The ICMP echo request failed because it contains an invalid option. case IPStatus.HardwareError: //HardwareError = 11008,The ICMP echo request failed because of a hardware error. case IPStatus.PacketTooBig: //PacketTooBig = 11009,The ICMP echo request failed because the packet containing the request is larger than the maximum transmission unit (MTU) of a node (router or gateway) located between the source and destination. The MTU defines the maximum size of a transmittable packet. case IPStatus.ParameterProblem: //ParameterProblem = 11015,The ICMP echo request failed because a node (router or gateway) encountered problems while processing the packet header. This is the status if, for example, the header contains invalid field data or an unrecognized option. case IPStatus.SourceQuench: //SourceQuench = 11016,The ICMP echo request failed because the packet was discarded. This occurs when the source computer's output queue has insufficient storage space, or when packetsarrive at the destination too quickly to be processed. case IPStatus.BadDestination: //BadDestination = 11018,The ICMP echo request failed because the destination IP address cannot receive ICMP echo requests or should never appear in the destination address field ofany IP datagram. For example, calling Overload:System.Net.NetworkInformation.Ping.Send and specifying IP address "000.0.0.0" returns this status. case IPStatus.BadHeader: //BadHeader = 11042,The ICMP echo request failed because the header is invalid. case IPStatus.UnrecognizedNextHeader://UnrecognizedNextHeader = 11043,The ICMP echo request failed because the Next Header field does not contain a recognized value. The Next Header field indicates the extension header type (ifpresent) or the protocol above the IP layer, for example, TCP or UDP. case IPStatus.IcmpError: //IcmpError = 11044,The ICMP echo request failed because of an ICMP protocol error. case IPStatus.DestinationScopeMismatch://DestinationScopeMismatch = 11045, The ICMP echo request failed because the source address and destination address that are specified in an ICMP echo message are not in the same scope. This istypically caused by a router forwarding a packet using an interface that is outside the scope of the source address. Address scopes (link-local, site-local, andglobal scope) determine where on the network an address is valid. } return IPStatusCategory.Failed; } return IPStatusCategory.Failed; } #endregion private elemek } #endregion PingCycle class public enum PingerStatus { NotExisting = 2, Still = 1, Operating = 0, } } /// /// TCP Ping eszközök /// public static class PingTool { /// /// Elérhető e az állomás? /// /// Ip, vagy host név /// timeout /// public static bool IsHostAccessible(string hostNameOrAddress, int timeOut = 1000) { PingReply reply = Ping(hostNameOrAddress, timeOut); return reply.Status == IPStatus.Success; } /// /// Visszadja az állomás ping idejét (millisecundum) /// /// Ip, vagy host név /// timeout /// public static long GetPingTime(string hostNameOrAddress, int timeOut = 1000) { PingReply reply = Ping(hostNameOrAddress, timeOut); return reply.RoundtripTime; } /// /// Visszadja az állomás ping szerinti státuszát (IPStatus) /// /// Ip, vagy host név /// timeout /// /// public static IPStatus GetPingStatus(string hostNameOrAddress, int timeOut = 1000) { PingReply reply = Ping(hostNameOrAddress, timeOut); return reply.Status; } /// /// Ping /// /// Ip, vagy host név /// timeout /// PingReply public static PingReply Ping(string hostNameOrAddress, int timeOut = 1000) { Ping ping = new Ping(); return ping.Send(hostNameOrAddress, timeOut); } /// /// Ping specifikált adatokkal /// /// Ip, vagy host név /// timeout /// ping adatok /// PingReply public static PingReply Ping(string hostNameOrAddress, int timeOut, byte[] buffer) { if (buffer.Length > 65500) { throw new ArgumentException("Ping data too big! Maximum 65500 bytes allowed!"); } Ping ping = new Ping(); return ping.Send(hostNameOrAddress, timeOut, buffer); } /// /// Ping specifikált adatokkal és beállításokkal (PingOptions) /// /// Ip, vagy host név /// timeout /// ping adatok /// ping beállítások /// PingReply public static PingReply Ping(string hostNameOrAddress, int timeOut, byte[] buffer, PingOptions options) { if (buffer.Length > 65500) { throw new ArgumentException("Ping data too big! Maximum 65500 bytes allowed!"); } Ping ping = new Ping(); return ping.Send(hostNameOrAddress, timeOut, buffer, options); } } /// /// IPv4 kezeléssel kapcsolatos eszközök /// public static class IPv4Tool { /// /// Visszad egy IPAddress osztályt, amit a megadott byte értékekből épít fel /// /// /// public static IPAddress BuildIPAddress(params byte[] ip) { if (ip.Length != 4) { throw new ArgumentException("Invalid IP! Specific 4 byte value for valid IP address!"); } return new IPAddress(ip); } public static IPAddress BuildIPAddress(string ipOrHostname) { IPAddress ip; if (IPAddress.TryParse(ipOrHostname, out ip)) { // IP return ip; } else { // Hostname try { IPHostEntry hostEntry; hostEntry = Dns.GetHostEntry(ipOrHostname); foreach (var address in hostEntry.AddressList) { if (address.AddressFamily == AddressFamily.InterNetwork) { return address; } } throw new ArgumentException(String.Format("Bad input argument! (Argument is not Ip or DNS resorvable host name.)", ipOrHostname)); } catch (Exception ex) { throw new ArgumentException(String.Format("Bad input argument! (Argument is not Ip or DNS resorvable host name.)", ipOrHostname), ex); } } } } /// /// MAC address lekérdezése IP alapján /// public static class MACTool { /// /// Gets the MAC address () associated with the specified IP. /// /// The remote IP address. /// The remote machine's MAC address. public static PhysicalAddress GetMacAddress(IPAddress ipAddress) { const int MacAddressLength = 6; int length = MacAddressLength; var macBytes = new byte[MacAddressLength]; SendARP(BitConverter.ToInt32(ipAddress.GetAddressBytes(), 0), 0, macBytes, ref length); return new PhysicalAddress(macBytes); } public static PhysicalAddress GetMacAddress(string ipAddressOrHostName) { return MACTool.GetMacAddress(IPv4Tool.BuildIPAddress(ipAddressOrHostName)); } public static PhysicalAddress GetMacAddress(params byte[] ipAddress) { return MACTool.GetMacAddress(IPv4Tool.BuildIPAddress(ipAddress)); } public static string ToString(this PhysicalAddress mac, char byteSeparator) { return HexString.ByteArrayToHexViaLookup32(mac.GetAddressBytes(), byteSeparator); } /// /// Netbiostól kér a mac címet, csak netbiost megvalósító eszközökre működik!!! /// Elég lassú... /// /// /// public static string GetMacAddressFromNetBios(string ipAddress) { string macAddress = string.Empty; if (!PingTool.IsHostAccessible(ipAddress)) { return String.Empty; } try { ProcessStartInfo processStartInfo = new ProcessStartInfo(); Process process = new Process(); if (Environment.Is64BitOperatingSystem) { string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + "\\sysnative"; processStartInfo.FileName = Path.Combine(filePath, "nbtstat"); } else { processStartInfo.FileName = "nbtstat"; } processStartInfo.RedirectStandardInput = false; processStartInfo.RedirectStandardOutput = true; processStartInfo.Arguments = "-a " + ipAddress; processStartInfo.UseShellExecute = false; process = Process.Start(processStartInfo); string line = null; do { line = macAddress = process.StandardOutput.ReadLine(); if (line != null) { if (macAddress.Trim().ToLower().IndexOf("mac address", 0) > -1) { macAddress = line; break; } } } while (line != null); process.WaitForExit(); if (macAddress.IndexOf('=') > -1) { macAddress = macAddress.Substring(macAddress.IndexOf('=') + 1); } macAddress = macAddress.Trim(); } catch (Exception e) { // Something unexpected happened? Inform the user // The possibilities are: // 1.That the machine is not on the network currently // 2. The IP address/hostname supplied are not on the same network // 3. The host was not found on the same subnet or could not be // resolved } return macAddress; } /// /// ARP query kiküldése /// /// /// /// /// /// // http://www.codeproject.com/KB/IP/host_info_within_network.aspx [System.Runtime.InteropServices.DllImport("iphlpapi.dll", ExactSpelling = true)] static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref int PhyAddrLen); } public static class HexString { private static readonly uint[] _lookup32 = CreateLookup32(); private static uint[] CreateLookup32() { var result = new uint[256]; for (int i = 0; i < 256; i++) { string s = i.ToString("X2"); result[i] = ((uint)s[0]) + ((uint)s[1] << 16); } return result; } public static string ByteArrayToHexViaLookup32(byte[] bytes, char separator) { var lookup32 = _lookup32; byte multipier = 2; int length = bytes.Length * 2; if (separator != '\0') { length = bytes.Length * 3 - 1; multipier = 3; } var result = new char[length]; for (int i = 0; i < bytes.Length; i++) { var val = lookup32[bytes[i]]; result[multipier * i] = (char)val; result[multipier * i + 1] = (char)(val >> 16); if (separator != '\0' && i != bytes.Length - 1) { result[multipier * i + 2] = separator; } } return new string(result); } } }