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

目录
  • 1、简单上手
  • 2、使用并行计算
  • 3、添加异步编程
  • 4、补充

经常要检测某些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#网络小程序内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用C#实现基于TCP和UDP协议的网络通信程序的基本示例

    C#中使用TCP通信 TCP通信需要通信双方都在线,所以需要先启动服务端进行监听,客户端才能获得连接,服务端代码: static void Main(string[] args) { TcpClient client = null; NetworkStream stream = null; byte[] buffer = null; string receiveString = null; IPAddress localIP = IPAddress.Parse("127.0.0.1")

  • c#多线程网络聊天程序代码分享(服务器端和客户端)

    XuLIeHua类库 复制代码 代码如下: using System;using System.Collections;  using System.Collections.Generic;using System.Threading;  using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;using System.Text;using System.IO;using Sy

  • 详解C# 网络编程系列:实现类似QQ的即时通信程序

    引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net类库去实现它们的.为了让大家更好的理解我们平常中常见的软件QQ的工作原理,所以在本专题中将利用前面专题介绍的知识来实现一个类似QQ的聊天程序.  一.即时通信系统 在我们的生活中经常使用即时通信的软件,我们经常接触到的有:QQ.阿里旺旺.MSN等等.这些都是属于即时通信(Instant Messenger,IM)软件,IM是指所有能够即时发送和接收互联网消息的软件. 在前面专题

  • 使用Typescript开发微信小程序的步骤详解

    Typescript的优势咱不需要赘述太多,有兴趣可以参考(https://www.typescriptlang.org/).今天给大家分享一下如何在微信小程序(或者其他同类小程序)开发中使用Typescript. 这个分两种情况,最简单的做法就是在创建项目时,选择Typescript这个选项,如下图所示.但要注意,这个选项只有在选择"Use no cloud service"才有,而另外一种Mini Program Cloud Base则不支持.这个可能是开发工具还没有跟上吧,希望以

  • 在docker中部署tomcat并且部署java应用程序的步骤详解

    先给大家简单说下Docker的概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. 1.先说如何在docker中部署tomcat 第一步:root用户登录在系统根目录下创建文件夹tomcat7,命令如:mkdir tomcat7,并且切换到该目录下:cd tomcat7: 第二步:创建Dockerfile,命令如:touch Docker

  • 微信小程序 WXDropDownMenu组件详解及实例代码

    微信小程序 WXDropDownMenu组件详解,这里给个小的示例,帮助大家学习理解, 功能: 适用于商品列表筛选与功能菜单跳转 先来看下效果图: 思路与步骤: 布局方面,整体使用dl来写,二级包在dd中,用ul li来写:交互方面,点击某一级菜单,关闭兄弟子菜单,点击某子菜单关闭所有菜单. 1.使用dt做出第一级菜单 2.使用dd嵌套第二级菜单,初始隐藏.position为absolute,使用z-index浮出页面层 /*总菜单容器*/ .menu { display: block; hei

  • 微信小程序 template模板详解及实例

    微信小程序 template模板详解及实例 首先看一些官方的一些介绍. 模板:模板功能是通过对template 标签的属性 name="" 去创建不同模板,通过is="name的值"来使用. 通过上面两张图,大概能看出,使用模板可以为大量类似的布局带来便利.下面看一下我自己的一个Demo. 先放出效果图(数据来自聚合数据) 可以看到,除了选项个数的差别之外,其他布局是相同的. 下面的每一道题的模板. <template name="carItem&q

  • 微信小程序 解析网页内容详解及实例

    微信小程序 解析网页内容详解 最近在写一个爬虫,需要将网页进行解析供微信小程序使用.文字和图片解析都好说,小程序也有对应的text和image标签可以呈现.而更复杂的,比如表格,则比较棘手,不管是服务端解析还是小程序呈现都很费劲,也很难覆盖所有情况.于是我想,将表格对应的HTML代码转成图片,不失为一种变通的方法. 这里我们采用node-webshot模块,它对PhantomJS进行了轻量封装,可以轻松地将网页以截图形式保存下来. 首先安装Node.js和PhantomJS,然后新建一个js文件

  • 微信小程序 navbar实例详解

    微信小程序 navbar实例详解 实现效果图: data typeList: [ { name: "日报", id: "1" }, { name: "周报", id: "2" }, { name: "月报", id: "3" }, { name: "目录", id: "4" }] js that.setData({ dateValue: util.

  • 微信小程序 页面传值详解

    微信小程序 页面传值详解 一. 跨页面传值. 1 . 用 navigator标签传值或 wx.navigator, 比如 这里将good_id=16 参数传入detail页面, 然后detail页面的 onload方法内接受. 如果需要传多个参数, 用 & 链接即可 如果要传 数组, 字典等复杂类型, 要先用 JSON.stringify() 转成字符串传递. 注 : 如果转化的字符串中 有"?"这个符号, 则只会传递"?"以前的字符串, 这个问题我猜想可能

  • 微信小程序 require机制详解及实例代码

    微信小程序 require机制详解 一, JS模块加载:一次性加载全部JS, 但并不一定立即执行. 先提一提微信小程序架构: 类浏览器 -> HTTP本地服务 -> 云端服务 微信小程序运行的架构,基本上是浏览器 -> HTTP本地服务 -> 云端服务, HTTP本地服务用来读取本地文件或者代理云端的文件资源.读取项目中JS文件, 是由HTTP本地服务取本地存储的脚本文件. 似乎比较简单,一个HTML 引用所有JS文件 既然采用了这种架构,那微信小程序就类似浏览器那样,借助一个HT

  • 微信小程序 template模板详解及实例代码

    微信小程序 template模板详解 如下图,我在做华企商学院小程序的时候,课程搜索结果页和课程列表页结构是完全一样的,这时就非常适合使用模板来完成页面搭建.实现一次定义,到处使用. 模板 一.定义模板 1.新建一个template文件夹用来管理项目中所有的模板: 2.新建一个courseList.wxml文件来定义模板: 3.使用name属性,作为模板的名字.然后在<template/>内定义代码片段. 注意: a.可以看到一个.wxml文件中可以定义多个模板,只需要通过name来区分: b

  • 微信小程序模版渲染详解

    微信小程序的界面程序支持html语法,多加了一部分标签,如view.block.templete等. 模版渲染 index.wxml <view> <p>{{helloWord}}</p> </view> 其中{{}}里面包含的内容你可以理解为一个变量,怎么让程序解析出{{helloWord}}变量 在index.js 中注册这个变量 var json = { data:{ "helloWord" : "hello world&

随机推荐