zoukankan      html  css  js  c++  java
  • C#编程_单线程IP地址解析

    单线程IP地址解析

    目标程序

    1. 界面如下图

    image-20200301223944746

    1. 设计方法:完成单个IP地址解析,循环调用方法,完成扫描。
    2. 注意用stopwatch计算时间。

    实现思路

    1. 先知道怎么解析一个单个的IP地址。
    2. 用循环的方法解析多个IP地址。
    3. 设计程序的界面
    4. 设计事件

    实现过程

    在控制台中尝试过程

    //实现的思路
    //扫描的地址是自己设定的,我们需要设置变量来保存它们。
    //扫描的IP地址由两端组成,一个地址前缀,另外一部分时起始值和终止值
    //我们需要输出的是IP地址,扫描时间,和dns主机名
    //IP地址可以由IPAddress.Parse转换
    //可以通过Dns.GetHostEntry来解析
    //扫描时间可以用stopwatch来统计
    //还需要判断IP地址是否合法
        string addressPrefix = "127.0.0.";//用来存储地址前缀
        int startingValue = 1;//存放起始值
        int stopingValue = 2;//存放终止值
     // if (startingValue <= stopingValue && startingValue > 0 &&     startingValue <= 255 && stopingValue > 0 && stopingValue <= 255)
     //{不用if判断即可
     //用循环来扫描多个IP地址
        for (int i = startingValue; i <= stopingValue; i++)
             {
                    string ipString = addressPrefix + i;
                    IPAddress ip;//不能直接定义在try里面,不然出了try就不能用了
                    IPHostEntry iPHostEntry;
                    string iphostname;
                    try//判断是否合法
                    {
                        // IPAddress ip = IPAddress.Parse(ipString);
                        ip = IPAddress.Parse(ipString);
                        //Dns解析
                        //  IPHostEntry iPHostEntry = Dns.GetHostEntry(ip);
                        //  string iphostname = iPHostEntry.HostName;//获取ip的主机名
                        //  Console.WriteLine($"扫描地址:{ip},扫描用时,主机DNS名称:{iphostname}");
                        //不能大篇幅的try
                        //要精确点
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("IP地址不合法");
                        break;
                    }
                    Stopwatch sw = new Stopwatch();//实例化一个秒表对象sw
                    sw.Start();//秒表开始
                    try
                    { //Dns解析
    
                        iPHostEntry = Dns.GetHostEntry(ip);
                        iphostname = iPHostEntry.HostName;//获取ip的主机名
                        sw.Stop();//秒表结束
                    }
                    catch (Exception ex)
                    {
                        iphostname = "不在线";
                    }
                  
                    long time = sw.ElapsedMilliseconds;//获取这段过程的时间
                    Console.WriteLine($"扫描地址:{ip},扫描用时:{time}毫秒,主机DNS名称:{iphostname}");
                }
                //string ipString = addressPrefix + startingValue;//拼接成IP地址字符串
                Console.ReadLine();
            }
            /*  else
              {
                  Console.WriteLine("IP地址不合法");
                  Console.ReadLine();
              }*//
    

    设计WPF界面

    <Window x:Class="WpfApp_SingleThreadIPScan.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp_SingleThreadIPScan"
            mc:Ignorable="d"
            Title="单线程IP扫描" Height="450" Width="800"
            WindowStartupLocation="CenterScreen">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <GroupBox Grid.Row="0" Header="扫描的IP地址范围" VerticalContentAlignment="Center" Padding="10">
                <DockPanel>
                    <Label DockPanel.Dock="Left" Content="地址前缀:"/>
                    <TextBox Name="txt1" Text="192.168.1."/>
                    <Label Content="起始值:" Margin="15 0 0 0"/>
                    <TextBox Name="txtStart" Text="102" Margin="0,4,0,0" VerticalAlignment="Top"/>
                    <Label Content="终止值:" Margin="15 0 0 0"/>
                    <TextBox Name="txtEnd" Text="105"/>
                    <Button Name="btn1" Width="60" VerticalAlignment="Center" Content="开始扫描" Click="Button_Click"/>
                </DockPanel>
            </GroupBox>
            <Label Name="labelError" Grid.Row="1" Background="Red" Foreground="White"
                  Content="IP地址有错,请更正!" HorizontalContentAlignment="Center" />
            <GroupBox Grid.Row="2" Header="扫描信息">
                <ListBox x:Name="listBoxInfo"/>
            </GroupBox>
        </Grid>
    </Window>
    

    后台代码

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace WpfApp_SingleThreadIPScan
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
    
            public MainWindow()
            {
                InitializeComponent();
                labelError.Visibility = Visibility.Collapsed;//刚开始的时候隐藏报错的标签
            }
    
            private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
            {
                string strip1 = txt1.Text + txtStart.Text;
                string strip2 = txt1.Text + txtEnd.Text;
                IPAddress ip1, ip2;
                if (IPAddress.TryParse(strip1, out ip1) == false || IPAddress.TryParse(strip2, out ip2) == false)
                {
                    btn1.IsEnabled = false;
                    labelError.Visibility = Visibility.Visible;
                    return;
                }
    
                else
                {
                    btn1.IsEnabled = true;
                    labelError.Visibility = Visibility.Collapsed;
                }
    
            }
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                int startvalue = int.Parse(txtStart.Text);
                int stopvalue = int.Parse(txtEnd.Text);
                if (startvalue > stopvalue)
                {
                    MessageBox.Show("起始值必需大于终止值,地址范围有误。请改正!");
                }
                listBoxInfo.Items.Clear();
                string ip = "";
                for (int i = startvalue; i <= stopvalue; i++)
                {
                    ip = txt1.Text + i;
                    Scan(ip);
    
                }
    
    
    
            }
    
            private void Scan(string ip)
            {
                string hostname;
                Stopwatch sw = Stopwatch.StartNew();
                try
                {
                    hostname = Dns.GetHostEntry(ip).HostName;
                }
                catch(Exception ex)
                {
                    hostname = "(不在线)";
                }
                sw.Stop();
                long time = sw.ElapsedMilliseconds;
                listBoxInfo.Items.Add($"扫描地址:{ip},扫描用时:{time}毫秒,DNS主机名:{hostname}");
            }
        } }
    
    

    所需要的知识

    IP地址

    一个IP地址由两部分组成:

    1. 网络号:识别该地址所属的网络,它由Internet权力机构分配。
    2. 主机号:指明网络内的主机,它由各个网络的管理员统一分配。

    编址方案:

    1. IPv4编址方案

      • 由4个字节(十进制表示)组成的二进制值进行识别,中间用圆点分开,这种方法叫做点分十进制表示法
    2. IPv6编址方案

      • 每个IP地址有16个字节(128位二进制数),其完整格式用8段16进制表示,各段之间用冒号分隔。

    子网掩码

    ​ 子网掩码用于屏蔽IP地址的一部分以区别网络标识和主机标识。子网掩码把所有的网络位(二进制)用1来标识,主机位用0来标识

    • 例如:如果将子网掩码设置为255.255.255.0,则对于IP地址192.168.1.X,其网络标示部分为192.168.1;主机标示为:X

    可以利用子网掩码判断两台计算机是否在同一子网内.

    • 将其IP地址和子网掩码做按位与运算,如果得到结果相同即在同一个子网内。

    端口

    image-20200301230615579
    • 物理上的端口。如ADSL Modem、集线器的接口。
    • 逻辑意义上的端口,即进程标识
      • 端口号的范围从0到65535
      • 1000以内的端口号大多被标准协议所占用,所以应用程序中可以自由使用的端口号一般都使用大于1000的值。如宝塔面板的8888端口。

    C#中关于IP地址转换的类

    • 提供网际协议IP地址的IPAddress类;
    • 包含IP地址和端口号的IPEndPoint类;
    • 为Internet或Intranet主机提供信息容器的IPHostEntry类。

    IPAddress类

    • 位于System.Net命名空间
    • 提供了对IP地址的转换和处理功能

    Parse方法:将IP地址字符串转换为IPAddress的实例。

     IPAddress ipa = IPAddress.Parse(ip);//把IP字符串转换为IPaddress类型
    

    但如果该字符串不是IP地址类型,会出现异常。所以我们需要进行异常处理。

    System.FormatException:“指定了无效的 IP 地址。”
    

    所以一般我们这样用:

      string ip = "127.0.0.1";//定义一个IP字符串
                //IPAddress ipa = IPAddress.Parse(ip);//把IP字符串转换为IPaddress类型
                try
                {
                    IPAddress ipa = IPAddress.Parse(ip);
                }
                catch
                {
                    Console.WriteLine("请输入正确的IP地址!");
                    Console.ReadLine();
                }
    
    AddressFamily属性
     //AddressFamily
                IPAddress ip = IPAddress.Parse("::1");
                IPAddress ip1 = IPAddress.Parse("127.0.0.1");
                if (ip.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    Console.WriteLine("该IP地址采用IPV6编址");
                    Console.ReadLine();
                }
    

    IPAddress类还提供了7个只读字段,分别代表程序中使用的特殊IP地址。

    常见只读字段

    Any 提供一个IPv4地址,指示服务端应侦听所有网络接口上的客户端活动,它等效于0.0.0.0
    Broadcast 提供IPv4网络广播地址,它等效于255.255.255.255
    IPv6Any 提供所有可用的IPv6地址
    IPv6Loopback 表示系统的IPv6回环地址,等效于::1
    Loopback 表示系统的IPv4回环地址,等效于127.0.0.1
    IPEndPoint类
    • 应用程序连接到主机上的服务所需的主机和端口信息。
    • 常用构造函数
    IPAddress localAdress = IPAddress.Parse("127.7.0.1");
                IPEndPoint iep = new IPEndPoint(localAdress, 21);//初始化IPEndPoint类
                string ipaddress = "IP地址为"+iep.Address;//此处利用拼接字符串把IPAddress转换为字符串型
                string port = "端口号为" + iep.Port;
                Console.WriteLine($"{ipaddress}
    {port}");
                Console.ReadLine();
    
    IPHostEntry类

    ​ 将一个域名系统(DNS)的主机名与一组别名和一组匹配的IP地址关联。该类一般和Dns类一起使用。

    域名解析

    为什么引入域名系统?

    • 网络主机使用IP地址来定位
    • IP难于记忆,需要用名称来表示主机
    • IP地址改变后,域名不变,仍可访问

    .NET框架在System.Net命名空间提供了Dns类完成解析

    方法名称
    GetHostAddresses 返回指定主机的Internet协议IP地址与该方法对应的还有异步方法
    GetHostEntry 将主机名或IP地址解析为IPHostEntry实例该方法对应的还有异步方法
    GetHostName 获取本地计算机的主机名
    GetHostAddresses方法

    指定主机的IP地址,返回一个IPAddress类型的数组。

    • public static IPAddress[] GetHostAddresses(string hostNameOrAddress);

      • 参数中的hostNameOrAddress表示要解析的主机名或IP地址。
    • 若hostNameOrAddress是IP地址,则直接返回此地址;若是空字符串,则返回本机所有IPv4和IPv6地址。

    IPAddress[] ips = Dns.GetHostAddresses("baidu.com"); //定义一个数组来存放从主机来解析的IPAddress类
                IPAddress[] ips1 = Dns.GetHostAddresses("www.cctv.com");
                IPAddress[] ips2 = Dns.GetHostAddresses("127.0.0.1");//若hostNameOrAddress是IP地址,则直接返回此地址;
                IPAddress[] ips3 = Dns.GetHostAddresses("");//若是空字符串,则返回本机所有IPv4和IPv6地址。
              
                foreach (var i in ips3)
                {
                    Console.WriteLine(i);
    
                }
                Console.ReadLine()
    
    GetHostEntry方法

    根据主机名或IP地址返回一个IPHostEntry实例,用于在DNS服务器中查询与某个主机名或IP地址关联的IP地址列表。

    • public static IPHostEntry GetHostEntry (string hostNameOrAddress)
    • hostNameOrAddress表示要解析的主机名或IP地址
    • 当参数为空字符串时,返回本地主机的IPHostEntry实例。
     IPHostEntry iPHostEntry = Dns.GetHostEntry("");
                var iplist = iPHostEntry.AddressList;//获取IP地址列表
                var hostname = iPHostEntry.HostName;//获取主机名
                foreach(var i in iplist)
                {
                    Console.WriteLine(i);
                }
                Console.WriteLine($"主机名字为{hostname}");
                Console.ReadLine();
    
    GetHostName方法

    该方法用于获取本机主机名。

     string hostname = Dns.GetHostName();
                Console.WriteLine($"本机的主机名为:{hostname}");
                Console.ReadLine();
    
  • 相关阅读:
    wrap,wrapall,wrapinner的区别:
    jqueryappend和appendTo的区别
    《Nagios系统监控实践》一书出版
    基于Python的密码生成程序的优化
    Puppet学习:pp文件权限问题
    依然看不清
    免费编程中文书籍索引
    Linux批量修改指定目录下的文件或文件夹权限
    puppet学习:文件夹权限的问题
    Zabbix探索:Zabbix API使用时的错误1
  • 原文地址:https://www.cnblogs.com/delongzhang/p/12422412.html
Copyright © 2011-2022 走看看