C#编程_单线程IP地址解析

oLeiShen 2020-03-05

单线程IP地址解析

目标程序

  1. 界面如下图

? C#编程_单线程IP地址解析

  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地址和子网掩码做按位与运算,如果得到结果相同即在同一个子网内。

端口

C#编程_单线程IP地址解析

  • 物理上的端口。如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}\n{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();

相关推荐