珂珂的个人博客 - 一个程序猿的个人网站

多线程域名查询工具

     

    为什么要做这个工具呢,其实网上有很多域名注册查询,但我需要把查询出的数据保存到数据库。之前单线程查询速度很慢,改为多线程后快了很多,界面是用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;
                }
            }));
        }
    }
}



上一篇:FYJ.Blogs开发系列(八)-自定义路由

下一篇:个人代码全部开源


0 评论

查看所有评论

给个评论吧