为什么要做这个工具呢,其实网上有很多域名注册查询,但我需要把查询出的数据保存到数据库。之前单线程查询速度很慢,改为多线程后快了很多,界面是用WPF做的
前台代码
<Window x:Class="DomainTool.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DomainTool" xmlns:c="clr-namespace:FYJ.Winui.Controls;assembly=FYJ.Winui" Title="域名查询工具@http://kecq.com" Height="400" Width="720"> <Window.Resources> <Style TargetType="TextBlock"> <Setter Property="VerticalAlignment" Value="Center"></Setter> <Setter Property="Margin" Value="5,0,0,0"></Setter> </Style> <Style TargetType="c:TextBoxEx"> <Setter Property="Height" Value="24"></Setter> <Setter Property="Margin" Value="5,0,0,0"></Setter> </Style> <Style TargetType="c:ComboBoxEx"> <Setter Property="Height" Value="24"></Setter> <Setter Property="Margin" Value="5,0,0,0"></Setter> </Style> <Style TargetType="c:CheckBoxEx"> <Setter Property="VerticalAlignment" Value="Center"></Setter> <Setter Property="Margin" Value="5,0,0,0"></Setter> </Style> <Style TargetType="Button"> <Setter Property="Margin" Value="5,0,0,0"></Setter> </Style> <local:ListViewItemColorConvert x:Key="itemConvert"></local:ListViewItemColorConvert> </Window.Resources> <DockPanel> <WrapPanel DockPanel.Dock="Top" Margin="0,20,0,0"> <TextBlock Text="域名"></TextBlock> <c:TextBoxEx Width="100" x:Name="txtDomain"></c:TextBoxEx> <TextBlock Text="后缀"></TextBlock> <c:ComboBoxEx Width="80" x:Name="comSuffix"> <ComboBoxItem IsSelected="True">.com</ComboBoxItem> <ComboBoxItem>.cn</ComboBoxItem> <ComboBoxItem>.net</ComboBoxItem> <ComboBoxItem>.org</ComboBoxItem> <ComboBoxItem>.cc</ComboBoxItem> <ComboBoxItem>.me</ComboBoxItem> <ComboBoxItem>.tv</ComboBoxItem> <ComboBoxItem>.com.cn</ComboBoxItem> <ComboBoxItem>.net.cn</ComboBoxItem> </c:ComboBoxEx> <TextBlock Text="长度"></TextBlock> <c:TextBoxEx Text="1" Width="30" x:Name="txtMinLength"></c:TextBoxEx> <TextBlock Text="-"></TextBlock> <c:TextBoxEx Text="4" Width="30" x:Name="txtMaxLength"></c:TextBoxEx> <TextBlock Text="分类"></TextBlock> <c:ComboBoxEx Width="150" x:Name="txtCate"> </c:ComboBoxEx> <TextBlock Text="状态"></TextBlock> <c:ComboBoxEx Width="100" x:Name="comStatus"> </c:ComboBoxEx> </WrapPanel> <WrapPanel DockPanel.Dock="Top" Margin="0,10,0,10"> <c:CheckBoxEx Content="仅数据库" x:Name="chkDbOnly"></c:CheckBoxEx> <Button Content="查询" Width="80" Margin="10,0,0,0" x:Name="btnQuery" Click="btnQuery_Click"></Button> <Button Content="停止" Width="80" x:Name="btnStop" Click="btnStop_Click"></Button> <Button Content="清空" Width="80" x:Name="btnClear" Click="btnClear_Click"></Button> <TextBlock Text="域名是精确查询,如果输入了则会忽略掉一切其它查询条件" Foreground="#FFA29A9A" FontSize="11"></TextBlock> </WrapPanel> <Grid DockPanel.Dock="Bottom" Margin="0,10,0,10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="200"></ColumnDefinition> <ColumnDefinition Width="150"></ColumnDefinition> </Grid.ColumnDefinitions> <c:TextBlockEx Text="就绪" Name="txtState"></c:TextBlockEx> <WrapPanel Grid.Column="1"> <TextBlock Text="数据库记录数:"></TextBlock> <c:TextBlockEx Name="txtDbCount" Text="0"></c:TextBlockEx> <TextBlock Text=" 网络查询:"></TextBlock> <c:TextBlockEx Name="txtNetCount" Text="0"></c:TextBlockEx> </WrapPanel> <c:ProgressBarEx Grid.Column="2" Name="progressBar1" ValueChanged="progressBar1_ValueChanged"></c:ProgressBarEx> </Grid> <c:LogListBox Height="100" x:Name="logList1" DockPanel.Dock="Bottom" ></c:LogListBox> <TabControl> <TabItem Header="已注册(0)" x:Name="txtIsRegisteredCount"> <DataGrid x:Name="dataGrid1" AutoGenerateColumns="False" IsReadOnly="True"> <DataGrid.Columns> <DataGridTemplateColumn Header="域名"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Domain}" Background="{Binding Path=Color,Converter={StaticResource itemConvert}}" Foreground="Black" ></TextBlock> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridHyperlinkColumn Binding="{Binding Path=Registered}" Width="150" Header="状态"/> <DataGridTextColumn Binding="{Binding Path=RegisterDatetimeString}" Width="150" Header="注册时间"/> <DataGridTextColumn Binding="{Binding Path=ExpireDatetimeString}" Width="150" Header="过期时间"/> </DataGrid.Columns> </DataGrid> </TabItem> <TabItem Header="未注册(0)" x:Name="txtNotRegisteredCount"> <DataGrid x:Name="dataGrid2" AutoGenerateColumns="False" IsReadOnly="True"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Domain}" Width="150" Header="域名"/> </DataGrid.Columns> </DataGrid> </TabItem> <TabItem Header="异常数(0)" x:Name="txtExceptionCount"> <DataGrid x:Name="dataGrid3" AutoGenerateColumns="False" IsReadOnly="True"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Domain}" Width="150" Header="域名"/> <DataGridTextColumn Binding="{Binding Message}" Width="300" Header="信息"/> </DataGrid.Columns> </DataGrid> </TabItem> </TabControl> </DockPanel> <Window.TaskbarItemInfo> <TaskbarItemInfo x:Name="taskbarItemInfo1"> </TaskbarItemInfo> </Window.TaskbarItemInfo> </Window>
后台代码
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Linq; using System.Text; using System.Threading; 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.Windows.Shell; namespace DomainTool { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { //线程数 private const int THREAD_COUNT = 10; private FYJ.Data.IDbHelper db = FYJ.Data.DbFactory.GetIDbHelper("domain"); private IDomainQuery query = new NetcnQuery(); private ObservableCollection<DomainModel> list = new ObservableCollection<DomainModel>(); private ObservableCollection<DomainModel> notRegisterlist = new ObservableCollection<DomainModel>(); private ObservableCollection<object> exceptionlist = new ObservableCollection<object>(); private CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); private ManualResetEvent mre = new ManualResetEvent(true); //初始化不等待 private AutoResetEvent eventFinished = new AutoResetEvent(false); //已注册数 private int isRegisteredCount = 0; //未注册数 private int notRegisterCount = 0; //异常数 private int exceptionCount = 0; //同步对象 private object sync = new object(); public MainWindow() { InitializeComponent(); } #region 初始化 protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); this.dataGrid1.ItemsSource = list; this.dataGrid2.ItemsSource = notRegisterlist; this.dataGrid3.ItemsSource = exceptionlist; LoadCate(); LoadState(); this.btnStop.IsEnabled = false; } //加载域名类型 private void LoadCate() { List<object> list = new List<object>(); //list.Add(new { Text = "全部", Value = 0 }); //list.Add(new { Text = "纯英文", Value = 1 }); //list.Add(new { Text = "纯数字", Value = 2 }); //list.Add(new { Text = "非0开头纯数字", Value = 21 }); list.Add(new { Text = "非0开头带4纯数字", Value = 22 }); list.Add(new { Text = "非0开头不带4纯数字", Value = 23 }); //list.Add(new { Text = "中文拼音", Value = 7 }); //list.Add(new { Text = "英文单词", Value = 8 }); //list.Add(new { Text = "杂米", Value = 9 }); //list.Add(new { Text = "中文", Value = 10 }); this.txtCate.ItemsSource = list; this.txtCate.SelectedValuePath = "Value"; this.txtCate.DisplayMemberPath = "Text"; this.txtCate.SelectedIndex = 0; } private void LoadState() { List<object> list = new List<object>(); list.Add(new { Text = "全部", Value = 0 }); list.Add(new { Text = "未注册", Value = 210 }); list.Add(new { Text = "已注册", Value = 211 }); this.comStatus.ItemsSource = list; this.comStatus.SelectedValuePath = "Value"; this.comStatus.DisplayMemberPath = "Text"; this.comStatus.SelectedIndex = 0; } #endregion private void InitValue() { this.btnQuery.IsEnabled = false; this.btnStop.IsEnabled = true; this.list.Clear(); this.logList1.Items.Clear(); this.progressBar1.Value = 0; this.txtDbCount.Text = "0"; this.txtNetCount.Text = "0"; this.isRegisteredCount = 0; this.notRegisterCount = 0; this.exceptionCount = 0; this.txtExceptionCount.Header = "异常数(0)"; } private async void btnQuery_Click(object sender, RoutedEventArgs e) { try { if (this.txtMaxLength.Text.Trim() == "") { MessageBox.Show("请输入一个最大长度"); return; } int maxLength = Convert.ToInt32(this.txtMaxLength.Text.Trim()); if (maxLength < 2) { MessageBox.Show("最大长度必须大于1"); return; } if (maxLength > 6) { MessageBox.Show("最大长度暂时不能超过6"); return; } //初始化值 InitValue(); cancelTokenSource = new CancellationTokenSource(); string tableName = "tb_domain_" + this.comSuffix.Text.Substring(1); string sql = "select Domain,RegisterDatetime,ExpireDatetime,Status from " + tableName + " where 1=1 "; if (this.txtDomain.Text.Trim() != "") { sql += " and Domain = '" + this.txtDomain.Text.Trim() + this.comSuffix.Text + "'"; } else { if (this.txtCate.SelectedValue.ToString() != "0") { sql += " and Cate=" + this.txtCate.SelectedValue; } if (this.txtMinLength.Text.Trim() != "") { sql += " and length(Domain)>=" + (Convert.ToInt32(this.txtMinLength.Text) + this.comSuffix.Text.Length); } if (this.txtMaxLength.Text.Trim() != "") { sql += " and length(Domain)<=" + (Convert.ToInt32(this.txtMaxLength.Text) + this.comSuffix.Text.Length); } if (this.comStatus.SelectedValue.ToString() != "0") { sql += " and Status=" + this.comStatus.SelectedValue; } } this.txtState.Text = "正在查询数据库..."; DataTable dt = new DataTable(); await Task.Factory.StartNew(() => { dt = db.GetDataTable(sql); }); this.txtDbCount.Text = dt.Rows.Count + ""; this.txtState.Text = "正在展示数据库数据..."; foreach (DataRow dr in dt.Rows) { DomainModel model = new DomainModel(); model.Domain = dr["Domain"].ToString(); if (dt.Rows[0]["RegisterDatetime"].ToString() != "") { model.RegisterDatetime = Convert.ToDateTime(dt.Rows[0]["RegisterDatetime"]); } if (dt.Rows[0]["ExpireDatetime"].ToString() != "") { model.ExpireDatetime = Convert.ToDateTime(dt.Rows[0]["ExpireDatetime"]); } model.Status = Convert.ToInt32(dt.Rows[0]["Status"]); this.dataGrid1.Dispatcher.Invoke((Action)(() => { list.Add(model); })); } //已被注册数 isRegisteredCount = list.Where(c => c.Status == 211).Count(); //未被注册数 notRegisterCount = list.Where(c => c.Status == 210).Count(); this.txtIsRegisteredCount.Header = "已注册(" + isRegisteredCount + ")"; this.txtNotRegisteredCount.Header = "未注册(" + notRegisterCount + ")"; if (this.chkDbOnly.IsChecked == true) { this.txtState.Text = "从数据库查询完毕,共查询到" + dt.Rows.Count + "条记录"; this.btnQuery.IsEnabled = true; this.btnStop.IsEnabled = false; return; } Queue<string> domains = new Queue<string>(); this.txtState.Text = "正在计算范围..."; await Task.Factory.StartNew(() => { domains = GetDomainList(); this.progressBar1.Maximum = domains.Count - dt.Rows.Count; }); List<Task> taskList = new List<Task>(); for (int i = 0; i < THREAD_COUNT; i++) { Task task = new Task(() => { ThreadWork(domains); }, cancelTokenSource.Token); taskList.Add(task); task.Start(); } //等待所有线程完成 await Task.Factory.StartNew(() => { Task.WaitAll(taskList.ToArray()); }); this.txtState.Text = "就绪"; } catch (Exception ex) { this.txtState.Text = ex.Message; } this.btnStop.IsEnabled = false; this.btnQuery.IsEnabled = true; } private void ThreadWork(Queue<string> domains) { if (cancelTokenSource.IsCancellationRequested) { this.logList1.AddErrorItem("线程" + Thread.CurrentThread.ManagedThreadId + "操作已被用户取消"); return; } mre.WaitOne(); Monitor.Enter(sync); if (domains.Count == 0) { return; } string domain = domains.Dequeue(); Monitor.Exit(sync); Monitor.Enter(sync); this.txtState.Text = "线程" + Thread.CurrentThread.ManagedThreadId + "正在查询... " + (this.progressBar1.Value) + "/" + this.progressBar1.Maximum; Monitor.Exit(sync); try { //Thread.Sleep(300); DomainModel model = this.QuerySingle(list, domain); this.logList1.AddItem("线程" + Thread.CurrentThread.ManagedThreadId + "查询" + domain + "成功"); } catch (Exception ex) { this.logList1.AddErrorItem("线程" + Thread.CurrentThread.ManagedThreadId + "查询" + domain + "失败:" + ex.Message); Monitor.Enter(sync); exceptionCount++; this.Dispatcher.Invoke(() => { this.exceptionlist.Add(new { Domain = domain, Message = ex.Message }); this.txtExceptionCount.Header = "异常数(" + exceptionCount + ")"; }); Monitor.Exit(sync); } if (domains.Count > 0) { ThreadWork(domains); } } private Queue<string> GetDomainList() { Queue<string> list = new Queue<string>(); //查询单个域名 if (this.txtDomain.Text.Trim() != "") { string domain = this.txtDomain.Text.Trim() + this.comSuffix.Text; list.Enqueue(domain); } else { int cate = Convert.ToInt32(this.txtCate.SelectedValue); if (cate == 21 || cate == 22 || cate == 23) { string mintemp = "1"; for (int i = 1; i < Convert.ToInt32(this.txtMinLength.Text.Trim()); i++) { mintemp += "0"; } string maxtemp = ""; for (int i = 0; i < Convert.ToInt32(this.txtMaxLength.Text.Trim()); i++) { maxtemp += "9"; } for (int i = Convert.ToInt32(mintemp); i <= Convert.ToInt32(maxtemp); i++) { string domain = i + this.comSuffix.Text; //域名是否存在不在这里判断 因为每次判断都要查询 效率太低了 //不限制4 if (cate == 21) { list.Enqueue(domain); } //带4 if (cate == 22) { if (i.ToString().Contains("4")) { list.Enqueue(domain); } } //不带4 if (cate == 23) { if (!i.ToString().Contains("4")) { list.Enqueue(domain); } } } } } return list; } private DomainModel QuerySingle(ObservableCollection<DomainModel> list, string domain) { if (String.IsNullOrEmpty(domain)) { throw new Exception("查询域名不能为空"); } //如果数据库已包含该域名 DomainModel model = this.list.Where(c => c.Domain == domain).FirstOrDefault(); if (model != null) { return model; } model = query.Query(domain); string tableName = "tb_domain_" + this.comSuffix.Text.Substring(1); string sql = "insert into " + tableName + " (Domain,Suffix,RegisterDatetime,ExpireDatetime,Status,Whois,Cate,ADD_DATE,UPDATE_DATE) values (@Domain,@Suffix,@RegisterDatetime,@ExpireDatetime,@Status,@Whois,@Cate,@ADD_DATE,@UPDATE_DATE)"; db.ExecuteSql(sql , db.CreateParameter("@Domain", model.Domain) , db.CreateParameter("@Suffix", this.comSuffix.Text) , db.CreateParameter("@RegisterDatetime", model.RegisterDatetime) , db.CreateParameter("@ExpireDatetime", model.ExpireDatetime) , db.CreateParameter("@Status", model.Status) , db.CreateParameter("@Whois", model.Whois) , db.CreateParameter("@Cate", this.txtCate.SelectedValue) , db.CreateParameter("@ADD_DATE", DateTime.Now) , db.CreateParameter("@UPDATE_DATE", DateTime.Now)); Monitor.Enter(sync); if (model.Status == 211) { isRegisteredCount++; this.Dispatcher.Invoke(() => { this.txtIsRegisteredCount.Header = "已注册(" + isRegisteredCount + ")"; this.list.Add(model); }); } if (model.Status == 210) { notRegisterCount++; this.Dispatcher.Invoke(() => { this.txtNotRegisteredCount.Header = "未注册(" + notRegisterCount + ")"; this.notRegisterlist.Add(model); }); } int netCount = Convert.ToInt32(this.txtNetCount.Text); this.txtNetCount.Text = (netCount + 1) + ""; this.progressBar1.Value = this.progressBar1.Value + 1; Monitor.Exit(sync); return model; } private void btnStop_Click(object sender, RoutedEventArgs e) { cancelTokenSource.Cancel(); this.btnQuery.IsEnabled = true; } private void btnClear_Click(object sender, RoutedEventArgs e) { this.Dispatcher.Invoke((Action)(() => { list.Clear(); notRegisterlist.Clear(); exceptionlist.Clear(); })); } private void progressBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { this.Dispatcher.Invoke((Action)(() => { this.taskbarItemInfo1.ProgressState = TaskbarItemProgressState.Normal; this.taskbarItemInfo1.ProgressValue = e.NewValue / this.progressBar1.Maximum; if (e.NewValue == this.progressBar1.Maximum) { this.taskbarItemInfo1.ProgressState = TaskbarItemProgressState.None; } })); } } }