题目描述:
创建一个WPF应用程式,用多任务扫描一个网段内的计算机,根据计算机的IP地址获取其主机域名。
XAML文件描述:
我用的是一个Canvers里面嵌套Grid,然后Grid分三行(分别是2*,1*,3*)。第一行里面放label和TextBox用于提示并且获取用户输入的网段。第二行errorLabel错误提示,我用的算法是错误时Visible,输入正确时Hidden。第三行里面放一个GroupBox,然后里面放一个ListBox,margin="3".
关于美工和界面设计我基本不会,属于完全的门外汉。虽说大二了,可是对photoshop还有设计学一无所知。每次的界面设计对我真的是煎熬(此刻难受五秒钟......)。
XAML文件代码实现:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas>
<GroupBox Header="扫描的IP地址:" Height="313" Width="507">
<Grid Height="293" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Label Content="地址前缀:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="24" Width="70"/>
<TextBox x:Name="qianzhui" HorizontalAlignment="Left" Height="23" Margin="80,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="78"/>
<Label Content="起始值:" HorizontalAlignment="Left" Margin="163,10,0,0" VerticalAlignment="Top" Height="24" Width="58"/>
<TextBox x:Name="qishi" HorizontalAlignment="Left" Height="23" Margin="221,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="90"/>
<Label Content="终止值:" HorizontalAlignment="Left" Margin="316,10,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="zhongzhi" HorizontalAlignment="Left" Height="23" Margin="382,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="103"/>
<Label x:Name="errorLable" Background="Red" Foreground="White" FontSize="19" Content="IP地址有错,请更正!" HorizontalAlignment="Center" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Center" Width="475" Height="36" HorizontalContentAlignment="Center"/>
<GroupBox Header="扫描信息:" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="2" VerticalAlignment="Top" RenderTransformOrigin="0.212,-1.15" Height="126" Width="475">
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="100" Margin="3" VerticalAlignment="Top" Width="444"/>
</GroupBox>
<Button Content="开始扫描" HorizontalAlignment="Left" Margin="163,55,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</GroupBox>
</Canvas>
咳咳,属性设置的很啰嗦并且不自然,我是不会告诉你我是用拖放的。其实老师课上讲过一次:“基本控件最好不要用拖放,因为那样是绝对的布局,使得软体的可移植性差”。可是啊,感觉总是找不到好的解决办法。
.CS文件代码实现:
using System;
using System.Collections.Generic;
using System.Linq;
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;
using System.Net;
using System.Threading;
namespace WpfApplication1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{ int n = 0;
public MainWindow()
{
DateTime taskBegin = DateTime.Now;
InitializeComponent();
qianzhui.Text = "192.168.1.";
qishi.Text = "102";
zhongzhi.Text = "105";
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
IPAddress ipstart;
IPAddress ipend;
if (IPAddress.TryParse(qianzhui.Text + qishi.Text, out ipstart) && IPAddress.TryParse(qianzhui.Text + zhongzhi.Text, out ipend))
{
errorLable.Visibility = Visibility.Hidden;
}
else
{
errorLable.Visibility = Visibility.Visible;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IPAddress ipstart;
IPAddress ipend;
listBox.Items.Clear();
n= int.Parse(zhongzhi.Text) - int.Parse(qishi.Text) + 1;
if (IPAddress.TryParse(qianzhui.Text + qishi.Text, out ipstart) && IPAddress.TryParse(qianzhui.Text + zhongzhi.Text, out ipend))
{
errorLable.Visibility = Visibility.Hidden;
for (int i = int.Parse(qishi.Text); i <= int.Parse(zhongzhi.Text); i++)
{
IPAddress ip = IPAddress.Parse(qishi.Text + i.ToString());
Thread t = new Thread(scan);
t.Start(ip);
}
}
else
{
errorLable.Visibility = Visibility.Visible;
}
}
private void scan(Object ip)
{
DateTime taskBegin = DateTime.Now;
DateTime begin = DateTime.Now;
IPAddress ipAddress = (IPAddress)ip;
string hostName;
try
{
hostName = Dns.GetHostEntry(ipAddress).HostName;
}
catch
{
hostName = "(不在线)";
}
DateTime end = DateTime.Now;
TimeSpan ts = end - begin;
listBox.Dispatcher.Invoke(() => listBox.Items.Add("扫描地址:" + ipAddress.ToString() + " 扫描用时:" + ts.TotalMilliseconds + "毫秒 " + " 主机名称:" + hostName));
n--;
if (n == 0)
{
DateTime taskEnd = DateTime.Now;
TimeSpan taskAll = taskEnd - taskBegin;
MessageBox.Show("扫描完毕!总用时:" + taskAll.TotalMilliseconds + "毫秒");
}
}
}
}
.CS代码的注意点:
1.因为要根据IP地址查询对应的主机名称,所以会用到.NET命名空间中的Dns类的域名解析功能,可以查询到每个IP对应的DNS名。但是GetHostEntry方法有个参数,也就是合法的IP这时就需要IPAddress类里的静态Parse方法,它可以将IP地址的字符串转化为IPAddress的实例。
2.因为是多任务异步执行 ,会用到多线程,老师讲过多个线程争夺相同的一个代码段会出现死锁的情况。为了避免,可以利用WPF控件的Dispatcher属性,它会自动在线程池里按照优先级对工作项进行调度。这里我用的是Invoke来注册(同步调用),好像是通过执行特定的委托来实现的,具体忘了==。
3.还有就是执行时间的问题了,不知道这样写有没有问题。
鼓励自己:
并不是自己记性不好,而是没有掌握,如果真的理解就不会忘。而从闻所未闻到如鱼得水,需要重复,希望自己能多点耐心,不要太过于急功近利。还有,明明是那女孩追我,反而自己搞得比人家还不自然,真是的,定力不够。哦,对了,可以抽空去图书馆啃啃高纳德前辈的《Java编程思想》,别忘了带上笔记本。