C#实现网络小程序的步骤详解

 更新时间:2022年12月27日 08:13:27   作者:dawn  
经常要检测某些IP地址范围段的计算机是否在线。有很多的方法,比如进入到网关的交换机上去查询、使用现成的工具或者编写一个简单的DOS脚本等等,这些都比较容易实现。本文将用C#来实现,感兴趣的可以了解一下

经常要检测某些IP地址范围段的计算机是否在线。

有很多的方法,比如进入到网关的交换机上去查询、使用现成的工具或者编写一个简单的DOS脚本等等,这些都比较容易实现。

现在使用C#来完成。

1、简单上手

公用函数:

        public static long IPToLong(string ip)
        {
            //将IP地址转换为长整数
            string[] ipBytes = ip.Split('.');
            long ipLong = 0;
            ipLong += long.Parse(ipBytes[0]) * 256 * 256 * 256;
            ipLong += long.Parse(ipBytes[1]) * 256 * 256;
            ipLong += long.Parse(ipBytes[2]) * 256;
            ipLong += long.Parse(ipBytes[3]);
            return ipLong;
        }
 
        public static string LongToIP(long ip)
        {
            //将长整数IP地址转换为实际的IP地址
            long ipLong = ip;
            string ipString = string.Empty;
            ipString += ipLong / 256 / 256 / 256 + ".";
            ipLong = ipLong % (256 * 256 * 256);
            ipString += ipLong / 256 / 256 + ".";
            ipLong = ipLong % (256 * 256);
            ipString += ipLong / 256 + ".";
            ipLong = ipLong % 256;
            ipString += ipLong;
            return ipString;
        }

点击【检测】按钮:

            DateTime startTime, endTime;
            startTime= DateTime.Now;
            listBox1.Items.Add(startTime.ToString());
            string startIP = textBox1.Text;
            string endIP = textBox2.Text;
 
            // 将起始IP地址和结束IP地址转换为长整数 
            long startIPLong = IPToLong(startIP);
            long endIPLong = IPToLong(endIP);
 
            Ping ping = new Ping();
            // 遍历IP地址范围 
            for (long i = startIPLong; i <= endIPLong; i++)
            {
                // 将整数转换为IP地址 
                string ip = LongToIP(i);
 
                // 输出 
                PingReply pingReply = ping.Send(ip);
                if (pingReply.Status == IPStatus.Success)
                {
                    listBox1.Items.Add( ip + "=>计算机在线");
                }
                else
                {
                    listBox1.Items.Add(ip);
                }
 
            }
            endTime = DateTime.Now;
            listBox1.Items.Add(endTime.ToString());
            listBox1.Items.Add("OK:" + (endTime - startTime).ToString());

执行时没有问题的,可以出来结果,问题是界面卡顿了。

执行的时间也很长,执行需要1分21秒。

这个结果不能接受,需要对程序加以改进。

2、使用并行计算

不需要改动公用代码,只需要改动检测部分。

            Dictionary<string, string> ipResults = new Dictionary<string, string>();
 
            DateTime startTime, endTime;
            startTime = DateTime.Now;
            listBox1.Items.Add(startTime.ToString());
 
            string startIP = textBox1.Text;
            string endIP = textBox2.Text;
 
            // 将起始IP地址和结束IP地址转换为整数 
            long startIPLong = IPToLong(startIP);
            long endIPLong = IPToLong(endIP);
 
            // 创建一个可以存储IP地址的List
            List<string> ipList = new List<string>();
 
            for (long i = startIPLong; i <= endIPLong; i++)
            {
                // 将整数转换为IP地址 
                string ip = LongToIP(i);
                ipList.Add(ip);
                ipResults.Add(ip,"");
                listBox1.Items.Add(ip);
            }
 
            // 开启并行计算
            Parallel.ForEach(ipList, (ip) =>
            {
            // 创建一个新的Ping类
            Ping pingSender = new Ping();
            // 发送一个Ping请求
            var reply = pingSender.Send(ip);
 
            // 如果返回的状态是Success,则IP地址在线
            if (reply.Status == IPStatus.Success)
            {
                ipResults[ip] = "在线";
                ChangeIPStatus(ip,"在线");
                }
                else
                {
                    ipResults[ip] = "NO";
                    ChangeIPStatus(ip, "NO");
                }
            });
 
            endTime = DateTime.Now;
            listBox1.Items.Add(endTime.ToString());
            listBox1.Items.Add("OK:" + (endTime - startTime).ToString());

增加一个公用函数:

       public void ChangeIPStatus(string ip,string S1)
        {
            // 定位到listbox中记录并更改IP是否在线
            int index = listBox1.Items.IndexOf(ip);
            listBox1.Items[index] = ip+" "+S1;
        }

出现问题:

⑴ 提示“C#线程间操作无效:从不是创建控件“textbox1”的线程访问它”,这个就简单设置Control.CheckForIllegalCrossThreadCalls=false即可解决;

⑵ 提示“listbox1包含的项太多”,这个是不是与并行计算开启的线程太多有关?考虑到本机是8核,保守一点,修改参数

Parallel.ForEach(ipList, new ParallelOptions() { MaxDegreeOfParallelism = MaxDegreeOfParallelism = Environment.ProcessorCount }, (ip) =>
{
    //执行代码   
}

程序可以正常运行了。

⑶ 界面依然阻塞,但用时更多了。

去ping255个地址,竟然用了12分32秒!!!这个真是不可忍受,最关键没有界面交互,这太不用户友好了!

3、添加异步编程

            Dictionary<string, string> ipResults = new Dictionary<string, string>();
 
            DateTime startTime, endTime;
            startTime = DateTime.Now;
            listBox1.Items.Add(startTime.ToString());
 
            string startIP = textBox1.Text;
            string endIP = textBox2.Text;
 
            // 将起始IP地址和结束IP地址转换为整数 
            long startIPLong = IPToLong(startIP);
            long endIPLong = IPToLong(endIP);
 
            // 创建一个可以存储IP地址的List
            List<string> ipList = new List<string>();
 
            for (long i = startIPLong; i <= endIPLong; i++)
            {
                // 将整数转换为IP地址 
                string ip = LongToIP(i);
                ipList.Add(ip);
                ipResults.Add(ip,"");
                listBox1.Items.Add(ip);
            }
 
            Task task = new Task(() =>
            {
                // 创建一个多线程
                Parallel.ForEach(ipList, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (ip) =>
                {
                    // 创建一个新的Ping类
                    Ping pingSender = new Ping();
                    // 发送一个Ping请求
                    var reply = pingSender.Send(ip);
 
 
                    if (reply.Status == IPStatus.Success)
                    {
                        listBox1.Invoke(new Action(() =>
                        {
                            int index = listBox1.Items.IndexOf(ip);
                            listBox1.Items[index] = ip + " " + "在线";
                        }));
                    }
                    else
                    {
                        listBox1.Invoke(new Action(() =>
                        {
                            int index = listBox1.Items.IndexOf(ip);
                            listBox1.Items[index] = ip + " " + "NO";
                        }));
                    }
 
                });
            });
 
            task.Start();
            Task.WaitAll();
            endTime = DateTime.Now;
            listBox1.Items.Add(endTime.ToString());
            listBox1.Items.Add("OK:" + (endTime - startTime).ToString());

好了,因为使用Task异步编程,界面也不再阻塞和卡顿了,不过运行多少时间不能准确得到,改动一下代码,就是将时间输出定位到任务完成:

            task.ContinueWith((t) =>
            {
                endTime = DateTime.Now;
                listBox1.Items.Add(endTime.ToString());
                listBox1.Items.Add("OK:" + (endTime - startTime).ToString());
            });

运行时间为1分41秒,界面不卡顿了。

可是运行仍然是逐个IP地址在ping,根本没有并行计算的效果。虽然使用了Parallel.ForEach,可能是由于线程需要等待导致资源开销过大,那么线程没有被有效地利用。

这其实与普通的使用线程来做没有什么区别了。

4、补充

⑴ 检测方法:

            string ipAddress = (string)obj;
            TcpClient client = new TcpClient();
            try
            {
                client.Connect(ipAddress, 80);
                //在线
            }
            catch (Exception ex)
            {
                //不在线
            }
            finally
            {
                client.Close();
            }

引用:

using System.Net.Sockets;

⑵ 检测输入的IP地址是否合法:

    IPAddress address;
    if (IPAddress.TryParse(ipAddress, out address))
    {
        // 检查IP地址是否为IPv4地址
        if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            return true;
    }else{
        return false;
    }

对于检测计算机在线与否没有好的方法?看那么多的网络小工具,肯定有!

先完成这个效果,后面再进行优化。

到此这篇关于C#实现网络小程序的步骤详解的文章就介绍到这了,更多相关C#网络小程序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#模拟链表数据结构的实例解析

    C#模拟链表数据结构的实例解析

    这篇文章主要介绍了C#模拟链表数据结构的实例解析,包括队双向链表的模拟方法,例子中队链表的操作也有很好的说明,需要的朋友可以参考下
    2016-04-04
  • C#实现任务栏通知窗口

    C#实现任务栏通知窗口

    作为程序员在享受的同时我们也不禁要问:这到底是怎么实现的呢?本文就利用Visual Studio .Net C# 2005以及.Net框架绘图技术来实现这种任务栏通知窗口。
    2015-10-10
  • C#基于Socket实现多人聊天功能

    C#基于Socket实现多人聊天功能

    这篇文章主要为大家详细介绍了C#基于Socket实现多人聊天功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • C#实现猜数字游戏

    C#实现猜数字游戏

    这篇文章主要为大家详细介绍了C#实现猜数字游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • C#程序员最易犯的编程错误

    C#程序员最易犯的编程错误

    这篇文章主要介绍了C#程序员最易犯的10个编程错误,了解这些错误能够更好地学习C#程序设计,感兴趣的小伙伴们可以参考一下
    2015-11-11
  • 再议C#中的装箱与拆箱的问题详解

    再议C#中的装箱与拆箱的问题详解

    本篇文章再次介绍了C#中的装箱与拆箱,这次们看下使用泛型和不使用泛型引发装箱拆箱的情况
    2013-05-05
  • C#开发WinForm项目实现HTML编辑器

    C#开发WinForm项目实现HTML编辑器

    这篇文章介绍了C#开发WinForm项目实现HTML编辑器的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 浅谈C#数组(一)

    浅谈C#数组(一)

    本篇文章小编要得大家介绍的是C#数组,数组是一种数据结构,它可以包含同一个类型的多个元素,如果需要使用同一类型的多个对象,可以使用数组和集合,需要的朋友可以参考下面文章的具体内容
    2021-09-09
  • C#利用XML创建Excel文档的实现方法

    C#利用XML创建Excel文档的实现方法

    这篇文章主要介绍了C#利用XML创建Excel文档的实现方法,需要的朋友可以参考下
    2014-08-08
  • C#中比较常用的DateTime结构的使用方法

    C#中比较常用的DateTime结构的使用方法

    这篇文章主要介绍了C#中比较常用的DateTime结构的使用方法,需要的朋友可以参考下
    2015-11-11

最新评论