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后我对线程又加深印象了。

 

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

posted @ 2010-11-01 16:51  Jöhan  阅读(397)  评论(0编辑  收藏  举报