开发者

C# multi-thread ping

I'm working on a network monitoring application, that pings a (not known) number of hosts. So far I have the code below. I've made a class PingHost with a function zping and I called it with the help of a timer once every 2 seconds to let the 2 pings to finish, even if one of them gets TimedOut. But I think a better solution is to generate a new thread for every ping, so that the ping of every host would be independent.

Can anyone give me a hint how to do this?

namespace pinguin
{
    public partial class Form1 : Form
    {
        public Form1()
        {

            InitializeComponent();


        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            PingHost caca = new PingHost();
            PingHost caca1 = new PingHost();
            this.label1.Text = caca.zping("89.115.14.160");
            this.label2.Text = caca1.zping("89.115.14.129");



        }

    }

    public class PingHost
    {


        public string zping(string dest)
        {
            Application.DoEvents();
            Ping sender = new Ping();
            PingOptions options = new PingOptions();
            options.DontFragment 开发者_如何学Python= true;

            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            int timeout = 50;
            int failed = 0;
            int pingAmount = 5;
            string stat = "";
            PingReply reply = sender.Send(dest, timeout, buffer, options);
            if (reply.Status == IPStatus.Success)
            {
                stat = "ok";
            }
            else
            {
                stat = "not ok!";
            }



            return stat;
        }
    }
}


If you use .NET 4 you can use Parallel.Invoke.


You could handle the Ping.PingCompleted event:

ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);

then use:

ping.SendAsync()

side note: Choose more suitable names for your classes and routines. PingHost is more suitable as a routine name


Once I wrote such a solution (it constantly pings about 300 machines):

public class ManyAdressPing {
    private readonly bool bAutoStarted;
    private readonly CancellationTokenSource cancel = new CancellationTokenSource();
    public ConcurrentDictionary<IPAddress, OneAddressPing> pingi = new ConcurrentDictionary<IPAddress, OneAddressPing>();
    public ManyAdressPing(bool AutoStarted = true) {
        bAutoStarted = AutoStarted;
    }
    public int CountPings => pingi.Count;
    public void AddPingAddress(IPAddress addr, int msTimeOut = 3000, int BetweenPing = 3000) {
        var oap = new OneAddressPing(addr, cancel.Token, msTimeOut, BetweenPing);
        if (bAutoStarted) oap.Start();
        pingi.TryAdd(oap.ipAddress, oap);
    }
    public void RemovePingAddress(IPAddress addr) {
        if (pingi.TryRemove(addr, out var p)) p.Stop();
    }
    public void Stop() {
        cancel.Cancel();
        foreach (var pair in pingi) pair.Value.Stop();
    }
    public PingReply GetReply(IPAddress addr) {
        if (pingi.ContainsKey(addr)) return pingi[addr].GetReply();
        return null;
    }
    public Tuple<long, long> GetSuccessOperation(IPAddress addr) {
        if (pingi.ContainsKey(addr)) return pingi[addr].GetSuccessOperation();
        return null;
    }
    public PingReply[] GetReply() {
        PingReply[] ret = pingi.Values.Select(x=>x.GetReply()).ToArray();
        return ret;
    }
    public PingInfo GetPingInfo(IPAddress addr) {
        if (pingi.ContainsKey(addr)) {
            var ret = new PingInfo();
            var p = pingi[addr];
            ret.reply = p.GetReply();
            ret.SuccessPing = p._SuccessReply;
            ret.FailPing = p._FailReply;
            ret.LastSuccessPing = p.LastSuccessfullPing;
            return ret;
        }

        return null;
    }
    public bool IsPinged(IPAddress addr) {
        if (pingi.ContainsKey(addr)) return true;
        return false;
    }
    public IPAddress[] GetAddressesPing() {
        return pingi.Keys.ToArray();
    }
}
public class PingInfo {
    public PingReply reply;
    public long SuccessPing = 0;
    public long FailPing = 0;
    public DateTime LastSuccessPing;
    public override string ToString() {
        return $"Sping: {SuccessPing} last={LastSuccessPing}, Fping:{FailPing}, reply:{reply}";
    }
}
public class OneAddressPing {
    public static byte[] bu = {
        0
    };
    public long _FailReply;
    public long _SuccessReply;
    private bool bStop = false;
    private readonly CancellationToken cancellationToken;
    public DateTime LastSuccessfullPing = DateTime.MinValue;
    public int mSecBetweenPing = 3000;
    public Ping ping;
    public PingOptions popt;
    private Task pTask;
    // Here is a self-written LIFO stack
    public LightQueue<PingReply> replys = new LightQueue<PingReply>(10);
    private readonly AutoResetEvent reset = new AutoResetEvent(false);
    private Logger log = null;
    private Task pinging = null;
    public OneAddressPing(IPAddress addr, CancellationToken ct, int timeOut = 3000, int BetweenPing = 3000, Logger _log =null) {
        ipAddress = addr;
        popt = new PingOptions();
        popt.DontFragment = false;
        cancellationToken = ct;
        mSecTimeOut = timeOut;
        mSecBetweenPing = BetweenPing;
        log = _log;
    }
    public int mSecTimeOut { get; set; } = 3000;
    public IPAddress ipAddress { get; set; }
    public int CountPings => replys.Length;
    private void SetReply(PingReply rep) {
        if (rep == null) return;
        replys.Put(rep);
        if (rep.Status == IPStatus.Success) {
            Interlocked.Increment(ref _SuccessReply);
            LastSuccessfullPing = DateTime.Now;
        } else {
            Interlocked.Increment(ref _FailReply);
        }
    }
    public async Task Start() {
        if (pTask == null || pTask.Status != TaskStatus.Running) {
            ping = new Ping();
            Task.Factory.StartNew(PingCircle, TaskCreationOptions.RunContinuationsAsynchronously | TaskCreationOptions.LongRunning);                 pTask = Task.Run(PingCircle, cancellationToken);
        }
    }
    public void Stop() {
        if (pTask.Status == TaskStatus.Running) {
            bStop = true;
            try {
                pTask.Wait(mSecTimeOut, cancellationToken);
            } catch (Exception ex) {
                log.ErrorSource($"Error ping stop: {ex.Message}");
            } 
        }
    }
    private async Task PingCircle() {
        while (cancellationToken.IsCancellationRequested == false && !bStop) {
            try {
                try {
                    PingReply rep = await ping.SendPingAsync(ipAddress, mSecTimeOut, bu,popt);
                    if (rep != null) SetReply(rep);
                } catch (PingException p) {
                    // ignore ping error
                    Debug.WriteLine($"error: {p}");
                } catch (Exception ee) {
                    log?.ErrorSource(ee);
                    Debug.WriteLine($"error: {ee}");
                }
                await Task.Delay(mSecBetweenPing, cancellationToken);
            } catch (Exception ee) {
                log?.ErrorSource(ee);
            }
        }
    }
    public PingReply GetReply() {
        if (replys.IsEmpty) return null;
        return replys.PeekLast(0);
    }
    public Tuple<long, long> GetSuccessOperation() {
        return new Tuple<long, long>(_SuccessReply, _FailReply);
    }
    public bool LongPingSuccess() {
        int ret = 0;
        for (int i = 0; i < 5; i++) {
            var r = replys.PeekLast(i);
            if (r.Status == IPStatus.Success) ret++;
        }

        if (ret > 2) return true;
        return false;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜