zoukankan      html  css  js  c++  java
  • C#中实现IP地址的排序

          这一切的开始要从同事手中的一个医疗项目开始。

          早上一到公司,就看到同事跟数据库连接干上了。要处理的问题是判断网络是否连通。因为如果你不去判断的话,系统只会提示说"sa"登录失败,却不告诉你是因为网络的原因,这会让人相当的郁闷。

          我们的客户可不喜欢看到这样"不明不白"的错误,于是我们要做的就是帮他"翻译"过来,让他们知道是因为你们的网络不通,先找网管来检查网络,等到不再提示网络问题的时候再给我们打电话。

          要知道跑来跑去是很浪费时间的。

          到这里我就想到Scan,它其中一个重要的功能就是扫描网络中在线的IP地址(当然这是需要些其他条件的,这里不是我要说的),于是就想到肯定能用C#来实现这个功能。

    于是就开始Google了,后来我就找到了下面的东西:


    在这里我用到了线程,如果直接处理的话,时间上有点不能接受。

          首先我们找到局域网中在线的IP(这里只处理了一个网段的,如果有时间的朋友也可以研究下怎么处理多网段的)

    下面就以192.168.0.0至192.168.0.255为例:

    var thread1; private void button2_Click(object sender, EventArgs e)
    {
        for (int iNum = 0; iNum < 255; iNum++)
        { //ScanIP是下面的方法名 
            thread1 = new Thread(new ParameterizedThreadStart(ScanIP)); //线程传值
            thread1.Start(iNum);
        }
    }
    

    这里很简单就只是一个循环,唯一看起来不一样的就是线程了。 

    这里把循环的iNum值传到线程里面去做为IP的最后一段组成:192.168.0.1的格式然后下面再用组合的IP判断网络是否连通。

          已经很久没碰线程这块儿了,还是回头看的以前在北大青鸟做的摇奖机项目,最终解决线程后一是高兴,高兴解决了问题,二是感觉我还在吃老本。

    我知道是我进步得太慢了,我在努力。

    又回到代码,不要忘了还需要导入线程的命名空间:

    using System.Threading;

    下面是循环调用的扫描方法ScanIP方法

    public void ScanIP(object iNum)
    {
        var ip = "192.168.0." + iNum.ToString();
        var ping = new System.Net.NetworkInformation.Ping();
        var options = new System.Net.NetworkInformation.PingOptions();
        options.DontFragment = true;
        string data = "aa";
        byte[] buffer = Encoding.ASCII.GetBytes(data); //Wait seconds for a reply. 
        int timeout = 1000;
        System.Net.NetworkInformation.PingReply reply = ping.Send("192.168.0." + iNum, timeout, buffer, options);
        SetLblText("正在扫描:" + ip + " - " + reply.Status.ToString(), label3); //Status返回两个状态,Success和TimedOut所以下面也可以写成 //
        if (Boolean.Parse(reply.Status.ToString()))
            if (reply.Status.ToString().ToUpper() != "TimedOut".ToUpper()) { SetListBoxItem(ip, listView1); } //thread1是在上面按钮事件哪里声明的
        thread1.Abort();
    }
    

          判断IP是否在线的那段代码我也是直接复制下来用的,都没有改过,囧。。。。。

    能实现这样的功能有很多种方法,起码我就找到了两种,觉得这几段看起来更想我想象中的。

          大概意思就是执行Cmd命令:ping -n 1 192.168.0.1,然后在返回的结果里面找是不是有"timeout”字样或者你也可以直接在Cmd里面执行:ping -n -1 255.265.65.89看看会返回什么,当然前提是你局域网里面没有这个网段的(要是你有我就,,,我就,,,当我没说-_-!)。

          如果没有返回TimedOut那么就表示它在线那么就加入ListView。(在系统中执行Ping你或许看到的是中文,代码应该不是中文,之所以这样判断是因为我并没有得到0到255的所有IP)

          如果有那么就表示请求超时了,当然这里也存在一个问题:比如说网络差而造成大量的丢包,或则说硬件错误的时候它不会提示你"timeout",这里点到为止继续说下面的代码。

    if里面的那个方法是一个委托,下面是代码:

    public delegate void AddOnLineIP(string Value, ListView LBName);
    
    public void SetListBoxItem(string Value, ListView LBName)
    {
        if (LBName.InvokeRequired)
        {
            AddOnLineIP OnLineIP = new AddOnLineIP(SetListBoxItem);
            LBName.Invoke(OnLineIP, new object[] { Value, LBName });
        }
        else LBName.Items.Add(new ListViewItem(new string[] { "", Value }));
    }
    public void SetListBoxItem(string Value, ListView LBName)
    {
        if (LBName.InvokeRequired)
        {
            AddOnLineIP OnLineIP = new AddOnLineIP(SetListBoxItem);
            LBName.Invoke(OnLineIP, new object[] { Value, LBName });
        }
        else LBName.Items.Add(new ListViewItem(new string[] { "", Value }));
    }
    

          这几句代码我能用,但现在的我还不能具体的解释出来,我的理解就是在线程里面如果要调用控件的话就需要这样用。

    囧囧更健康。


    下面开始点题了

    通过上面的代码我们就把在线的IP给找出来了,但是它的顺序却不是我想要的。于是我也跟它干上了。最后找到下面段看不大明白的代码:

    private static uint ConvertToUInt(string ip1)
    {
        string[] sip = ip1.Split('.');
        return (uint.Parse(sip[0]) << 24) | (uint.Parse(sip[1]) << 16) | (uint.Parse(sip[2]) << 8) | (uint.Parse(sip[3]));
    }
    

    主要就是<<没看懂,不知道是什么意思,知道的朋友可以说下,先谢了。

    这只是个通用方法,要让IP地址排序是这样调用的:

    private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
    {
        var IPS = new string[listView1.Items.Count];
        for (int i = 0; i < listView1.Items.Count; i++)
        {
            IPS[i] = listView1.Items[i].SubItems[1].Text;
        }
        listView1.Items.Clear(); //将IPS里面的顺序从组 
        Array.Sort<string>(IPS, new Comparison<string>(delegate (string ip1, string ip2)
        {
            return Comparer<uint>.Default.Compare(ConvertToUInt(ip1), ConvertToUInt(ip2));
        }));
        for (int i = 0; i < IPS.Length; i++)
        {
            listView1.Items.Add(new ListViewItem(new string[] { "", IPS[i].ToString() }));
        }
    }
    

          先声明了一个IPS数组长度为ListView1的长度,然后循环ListView1取出来放到数组里面在将这个数组放到ConvertToUInt里面去排序,调用排序的就是中间句Array.Sort那句调用上面的ConvertToUInt方法来实现排序。

          最后完了先把ListView1的Item项清空,然后再把刚才排序后的IPS数组给加到ListView1里面就成功了。


    差不多了,基本上就是这样了。

    在这里留个标记下次的时候就不用去翻以前的项目了,这篇Blog后我对线程又加深印象了。

    对于那些现在不懂的,以后再来回顾它。

  • 相关阅读:
    结束咯
    在Ubuntu上不能使用PPA下载
    月亮+大环
    piano
    花都论坛,广州花都本地生活
    LLVM的调用协议与内存对齐
    SALVIA 0.5.2优化谈
    LLVM随笔
    OS之争:永不停歇的战争(二,完结)
    OS之争:永不停歇的战争(一)
  • 原文地址:https://www.cnblogs.com/fxck/p/13077012.html
Copyright © 2011-2022 走看看