元始天尊 发表于 2015-3-8 15:20:53

我的新版dns加速器出炉啦!!!欢迎提出意见和建议

http://www.0xaa55.com/forum.php?mod=viewthread&tid=1265&extra=
    很多人可能看过我这个帖子《对彗星DNS加速器的分析(一)(二)》,在其中我详细描述了张慧星的dns加速器实现原理,在这个礼拜,今天我刚刚自己实现出来,取得初步成果,这1500行代码用boost和stl一气呵成,
预期可以支持ipv6 dns,批量测试/停止,解析域名镜像(如google),支持大dns库和自定义dns库,甚至以后和代理功能结合到一起。
    由于是初稿,因此有bug,这里贴出源码,给出工程,望和大家一起探讨改进之处,理论上说这个工具会是很强大的!
效果图:
工程地址:http://pan.baidu.com/s/1jGsvAoI
关于这个工具欢迎有兴趣研究这方面的各路高手一起和我探讨

重要代码:
functions.h
#pragma once
#ifndef FASTERDNS_COMMONHEADER
#define FASTERDNS_COMMONHEADER
#endif

#include <string>
#include <vector>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread.hpp>
#include <boost/thread/detail/thread_group.hpp>
#include <deque>
#include <set>
#include "sqlite3.h"

#define DATABASE "dnss.db"
#define CSVDATA "nameservers.csv"

class testSpeedData//每轮测试所用数据
{
public:
        testSpeedData(char* _ip, char* _location) :ip(_ip), location(_location)
        {
                responsetime = 0;
                testtime = 0;
                lefttime = 0;
                failtime = 0;
                timeout = 0;
        }
public:
        std::string ip;//DNS地址
        std::string location;//所在地
        int responsetime;//总响应时间
        int testtime;//总测试次数
        int lefttime;//剩余次数
        int failtime;//失败次数
        int timeout;//超时时间
};

typedef int(*DBCALLBACK)(void *NotUsed, int argc, char **argv, char **azColName);
typedef std::vector<std::string> spliter;
typedef std::vector<std::pair<std::string,std::string>> dbData;

//数据库相关
bool doadddata(dbData* dataparam, HWND progctrl);
bool dodeldata(std::vector<std::string>* dataparam, HWND progctrl);
bool getcount(int& count);
bool getdata(std::vector<testSpeedData>* dataparam, HWND listctrl, HWND statu, boost::mutex* mu);


//网络操作相关
bool dohttpconnect(const std::string& ip, uint32_t& timeout);
bool dodnsconnect(const std::string& ip, uint32_t& timeout, std::vector<uint8_t>& bufferdata);
void makedns(std::vector<uint8_t>& bufferdata, const std::string& testdomain);
void replaceXid(std::vector<uint8_t>& bufferdata, uint16_t Xid);
void resolveAnswer(std::vector<uint8_t>& bufferdata, std::set<std::string>& resolvedip, int originlen);

//系统设置相关
bool getinterface(std::vector<std::string>& interfaces);
bool setinterface(std::vector<std::string>& interfaces, std::vector<std::string>& addresss, HWND progctrl);

enum
{
        //解析CSV数据文件
        CSV_IP = 0,
        CSV_NAME,
        CSV_COUNTRYID,
        CSV_CITY,
        CSV_MAX,
        //解析普通数据文件
        COM_IP = 0,
        COM_LOCATION,
        COM_MAX,
        //端口
        PORT_HTTP = 80,
        PORT_DNS = 53,
        //DNS包
        SIZE_DNSHEADER = sizeof(DNS_HEADER),
        SIZE_DNSTAILER = 5,
        //值域
        INIT_THREADNUM = 1,
        LOW_THREADNUM = 0,
        HIGH_THREADNUM = 1000,
        INIT_TIMEOUT = 1000,
        LOW_TIMEOUT = 10,
        HIGH_TIMEOUT = 10000,
        INIT_TESTNUM = 1,
        LOW_TESTNUM = 0,
        HIGH_TESTNUM = 100,
        //显示列
        COL_IP = 0,
        COL_LOC,
        COL_RES,//平均响应时间
        COL_FAIL,//失败次数/总次数
        //其他
        IDC_PROGRESS = 12345,
        MAX_DOMAIN_LENGTH = 256,
        MAXS_RECVNUM = 65536,
        HTTP_CONNECTTIME = 5000,
        TIMER1_ID=10000,
};

class ipcontainer:public boost::noncopyable
{
public:
        static ipcontainer& getInstance();
        bool adddata(const std::string& ip, const std::string& addr);
        bool deldata(const std::string& ip);
        bool getdata(std::vector<testSpeedData>* dataparam,HWND listctrl);
        bool getcount(int& pcount);
        virtual ~ipcontainer();
private:
        ipcontainer();
        static int getdatacallback(void *NotUsed, int argc, char **argv, char **azColName);
        static int getcountcallback(void *NotUsed, int argc, char **argv, char **azColName);
private:
        sqlite3* db;
        static int* pcount;
        static std::vector<testSpeedData>* testdata;
        static HWND pwnd;
};

template<typename D>
class ThreadPool
{
public:
        ThreadPool(boost::mutex& _mu) :mu(_mu)
        {
                threadnum = 0;
                task = NULL;
        }

        virtual ~ThreadPool()
        {
                if (ppio)
                {
                        for (int i = 0; i < threadnum; i++)
                                delete ppio;
                        delete[]ppio;
                }
        }

        bool Attach(int _threadnum, std::deque<int>* _task, std::vector<D>* _dataarray, HWND _listview)
        {
                if (!_task || _task->empty() || !_dataarray)
                        return false;//任务未结束
                task = _task;
                dataarray = _dataarray;
                threadnum = _threadnum;
                listview = _listview;
                ppio = new boost::asio::io_service*;
                if (!ppio)
                        return false;
                for (int i = 0; i < threadnum; i++)
                {
                        ppio = new boost::asio::io_service;
                        if (!ppio)//模拟new[]的行为,释放之前成功分配的内存
                        {
                                for (int j = i-1; j >= 0; j--)
                                        delete ppio;
                                delete[]ppio;
                                return false;
                        }
                }
                return true;
        }

        bool Exec(void(*f)(int, std::vector<D>*, HWND))
        {
                try
                {
                        boost::thread_group tg;
                        //建立线程组
                        for (int i = 0; i < threadnum; i++)
                        {
                                tg.create_thread(boost::bind(&ThreadPool::wrapper, this, ppio,f));
                        }
                        //等待所有任务执行完毕
                        tg.join_all();
                }
                catch (...)
                {
                        //确保释放new
                        return false;
                }
                return true;
        }

private:
        //用于将task里的任务分配各给threadnum个活动线程,分配时要进行线程同步
        void wrapper(boost::asio::io_service* service, void(*f)(int, std::vector<D>*, HWND))
        {
                while (true)
                {
                        mu.lock();
                        if (task->empty())
                        {
                                mu.unlock();
                                return;
                        }
                        service->post(boost::bind(f, task->front(), dataarray, listview));
                        task->pop_front();
                        mu.unlock();
                        service->run();
                        service->reset();
                }
        }

private:
        int threadnum;
        HWND listview;
        boost::mutex& mu;//分配任务用锁
        std::deque<int>* task;//要分配的总任务索引
        std::vector<D>* dataarray;//原始数据
        boost::asio::io_service** ppio;//耗费的线程资源   
};

#pragma pack(push)
#pragma pack(2)
typedef struct _DNSANSWER_HEADER
{
        WORD Name;
        WORD Type;
        WORD Class;
        DWORD Timetolive;
        WORD Datalength;
}DNSANSWER_HEADER, *PDNSANSWER_HEADER;
#pragma pack(pop)

#define DNS_BYTE_FLIP_ANSWERHEADER_COUNTS(pHeader)\
        {\
        PDNSANSWER_HEADER _head = (pHeader); \
        INLINE_HTONS(_head->Name,                _head->Name);\
        INLINE_HTONS(_head->Type,                _head->Type); \
        INLINE_HTONS(_head->Class,                _head->Class); \
        INLINE_HTONS(_head->Timetolive, _head->Timetolive); \
        INLINE_HTONS(_head->Datalength, _head->Datalength); \
        }

class udpclient//只为做超时处理
{
public:
        udpclient(const boost::asio::ip::udp::endpoint& listen_endpoint) :socket_(io_service_, listen_endpoint), deadline_(io_service_)
        {
                deadline_.expires_at(boost::posix_time::pos_infin);
                check_deadline();
        }
        std::size_t receive(const boost::asio::mutable_buffer& buffer, boost::posix_time::time_duration timeout, boost::system::error_code& ec)
        {
                deadline_.expires_from_now(timeout);
                ec = boost::asio::error::would_block;
                std::size_t length = 0;
                socket_.async_receive(boost::asio::buffer(buffer), boost::bind(&udpclient::handle_receive, _1, _2, &ec, &length));
                do io_service_.run_one(); while (ec == boost::asio::error::would_block);
                return length;
        }
private:
        void check_deadline()
        {
                if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
                {
                        socket_.cancel();
                        deadline_.expires_at(boost::posix_time::pos_infin);
                }
                deadline_.async_wait(boost::bind(&udpclient::check_deadline, this));
        }
        static void handle_receive(const boost::system::error_code& ec, std::size_t length,
                boost::system::error_code* out_ec, std::size_t* out_length)
        {
                *out_ec = ec;
                *out_length = length;
        }
private:
        boost::asio::io_service io_service_;
        boost::asio::deadline_timer deadline_;
public:
        boost::asio::ip::udp::socket socket_;
};

class tcpclient//只为做超时处理
{
public:
        tcpclient() :socket_(io_service_), deadline_(io_service_)
        {
                deadline_.expires_at(boost::posix_time::pos_infin);
                check_deadline();
        }
        void connect(const boost::asio::ip::tcp::endpoint ep, boost::posix_time::time_duration timeout, boost::system::error_code& ec)
        {
                deadline_.expires_from_now(timeout);
                ec = boost::asio::error::would_block;
                socket_.async_connect(ep,boost::bind(&tcpclient::handle_connect, _1, &ec));
                do io_service_.run_one(); while (ec == boost::asio::error::would_block);
        }
private:
        void check_deadline()
        {
                if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
                {
                        socket_.cancel();
                        deadline_.expires_at(boost::posix_time::pos_infin);
                }
                deadline_.async_wait(boost::bind(&tcpclient::check_deadline, this));
        }
        static void handle_connect(const boost::system::error_code& ec, boost::system::error_code* out_ec)
        {
                *out_ec = ec;
        }
private:
        boost::asio::io_service io_service_;
        boost::asio::deadline_timer deadline_;
public:
        boost::asio::ip::tcp::socket socket_;
};


fasterdnsdlg.cpp

// FasterDNSDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "FasterDNS.h"
#include "FasterDNSDlg.h"
#include "SetDnsDlg.h"
#include "afxdialogex.h"
#include <boost/scoped_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/range.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/xpressive/xpressive.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <queue>
#include <fstream>
#include <set>
#include "functions.h"
#include <stdlib.h>
#include "ShowIp.h"
#include "GlobalSetting.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CFasterDNSDlg::CFasterDNSDlg(CWnd* pParent /*=NULL*/)
        : CDialogEx(CFasterDNSDlg::IDD, pParent)
{
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CFasterDNSDlg::DoDataExchange(CDataExchange* pDX)
{
        CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CFasterDNSDlg, CDialogEx)
        ON_WM_PAINT()
        ON_BN_CLICKED(IDC_ADDDNS, &CFasterDNSDlg::OnBnClickedAddDNS)
        ON_NOTIFY(LVN_GETDISPINFO, IDC_IPLIST, &CFasterDNSDlg::OnLvnGetdispinfoIplist)
        ON_COMMAND(ID_ABOUT, &CFasterDNSDlg::OnAbout)
        ON_COMMAND(ID_SETDNS, &CFasterDNSDlg::OnSetdns)
        ON_NOTIFY(HDN_ITEMCLICK, 0, &CFasterDNSDlg::OnHdnItemclickIplist)
        ON_NOTIFY(NM_RCLICK, IDC_IPLIST, &CFasterDNSDlg::OnNMRClickIplist)
        ON_COMMAND(ID_DELDNS, &CFasterDNSDlg::OnDeldns)
        ON_BN_CLICKED(IDC_ALLINONE, &CFasterDNSDlg::OnBnClickedAllinone)
        ON_BN_CLICKED(IDC_START, &CFasterDNSDlg::OnBnClickedStart)
        ON_BN_CLICKED(IDC_STOP, &CFasterDNSDlg::OnBnClickedStop)
        ON_BN_CLICKED(IDC_VIEWIP, &CFasterDNSDlg::OnBnClickedViewip)
        ON_WM_TIMER()
        ON_COMMAND(ID_ADDDNS, &CFasterDNSDlg::OnAdddns)
        ON_COMMAND(ID_MODIFY, &CFasterDNSDlg::OnModify)
        ON_COMMAND(ID_STARTALL, &CFasterDNSDlg::OnStartall)
        ON_COMMAND(ID_STOPALL, &CFasterDNSDlg::OnStopall)
        ON_COMMAND(ID_TESTIP, &CFasterDNSDlg::OnTestip)
        ON_COMMAND(ID_EXIT, &CFasterDNSDlg::OnExit)
        ON_COMMAND(ID_ALLINONE, &CFasterDNSDlg::OnAllinone)
        ON_COMMAND(ID_START, &CFasterDNSDlg::OnStart)
        ON_COMMAND(ID_STOP, &CFasterDNSDlg::OnStop)
END_MESSAGE_MAP()

BOOL CFasterDNSDlg::OnInitDialog()
{
        CDialogEx::OnInitDialog();
        SetIcon(m_hIcon, TRUE);                        // 设置大图标
        SetIcon(m_hIcon, FALSE);                // 设置小图标
        m_list = (CListCtrl*)GetDlgItem(IDC_IPLIST);
        m_list->SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
        RECT rt;
        m_list->GetClientRect(&rt);
        m_list->InsertColumn(COL_IP, "DNS地址", LVCFMT_LEFT, rt.right / 5);
        m_list->InsertColumn(COL_LOC, "所在地", LVCFMT_LEFT, rt.right / 5);
        m_list->InsertColumn(COL_RES, "响应时间", LVCFMT_LEFT, rt.right / 5);
        m_list->InsertColumn(COL_FAIL, "失败率", LVCFMT_LEFT, rt.right / 5);

        boost::thread(boost::bind(getdata, &dataarray, m_list->m_hWnd, GetDlgItem(IDC_STATU)->m_hWnd, &datamutex));
        issorting = false;
        maxtask = 0;
        repeattime = 3;
        threadnum = 3;
        timeout = 1000;
        SetDlgItemText(IDC_DOMAIN, "www.microsoft.com");
        SetTimer(TIMER1_ID, 1000, NULL);
        return TRUE;// 除非将焦点设置到控件,否则返回 TRUE
}

void CFasterDNSDlg::OnPaint()
{
        if (IsIconic())
        {
                CPaintDC dc(this); // 用于绘制的设备上下文
                SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
                int cxIcon = GetSystemMetrics(SM_CXICON);
                int cyIcon = GetSystemMetrics(SM_CYICON);
                CRect rect;
                GetClientRect(&rect);
                int x = (rect.Width() - cxIcon + 1) / 2;
                int y = (rect.Height() - cyIcon + 1) / 2;
                dc.DrawIcon(x, y, m_hIcon);
        }
        else
        {
                CDialogEx::OnPaint();
        }
}

void CFasterDNSDlg::OnBnClickedAddDNS()
{
        CFileDialogdlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "*.*", NULL);
        if (IDOK == dlg.DoModal())
        {
                //读取文件,解析出ip
                std::fstream file;
                std::string line;
                dbData toadd;
                boost::asio::ip::address addr;
                spliter splitvec;
                //获取大小
                file.open(dlg.GetPathName(), std::ios::in);
                file.seekg(0,std::ios::end);
                int totalsize = file.tellg();
                file.seekg(0,std::ios::beg);

                CProgressCtrl m_progctrl;
                m_progctrl.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 400, 50), this,
                        IDC_PROGRESS);
                m_progctrl.SetRange(0, 100);
                boost::mutex::scoped_lock mdata(datamutex);

                if (dlg.GetFileName() == CSVDATA)
                {
                        getline(file, line);//跳过第一行
                        while (!file.eof())
                        {
                                int pos2 = file.tellg();
                                m_progctrl.SetPos(int(100*(double)file.tellg()/totalsize));
                                getline(file, line);
                                boost::split(splitvec, line, boost::is_any_of(","));
                                try
                                {
                                        if (splitvec.size() < CSV_MAX)
                                                throw "Error";
                                        addr = addr.from_string(splitvec);
                                }
                                catch (...)
                                {
                                        break;
                                }
                                LVITEM item = { 0 };
                                item.mask = LVIF_TEXT;
                                item.iItem = dataarray.size();
                                item.lParam = item.iItem;
                                item.pszText = LPSTR_TEXTCALLBACK;
                                dataarray.push_back(testSpeedData((char*)splitvec.c_str(), (char*)(splitvec + " " + splitvec).c_str()));
                                m_list->InsertItem(&item);
                                toadd.push_back(make_pair(splitvec, splitvec + " " + splitvec));
                        }
                }
                else
                {//普通文件,ip地址和位置信息用逗号分隔
                        while (!file.eof())
                        {
                                m_progctrl.SetPos(int(100*(double)file.tellg() / totalsize));
                                getline(file, line);
                                boost::split(splitvec, line, boost::is_any_of(","));
                                try
                                {
                                        if (splitvec.size() < COM_MAX)
                                                throw "Error";
                                        addr = addr.from_string(splitvec);
                                }
                                catch (...)
                                {
                                        break;
                                }
                                LVITEM item = { 0 };
                                item.mask = LVIF_TEXT;
                                item.iItem = dataarray.size();
                                item.lParam = item.iItem;
                                item.pszText = LPSTR_TEXTCALLBACK;
                                dataarray.push_back(testSpeedData((char*)splitvec.c_str(), (char*)splitvec.c_str()));
                                m_list->InsertItem(&item);
                                toadd.push_back(make_pair(splitvec, splitvec));
                        }
                }
                file.close();
                ProgressThread("正在添加",doadddata,&toadd);
        }
}

template<typename F,typename D>
void CFasterDNSDlg::ProgressThread(LPCTSTR wndname,F& threadfunc,D paramdata)
{
        CProgressCtrl m_progctrl;
        m_progctrl.Create(WS_CHILD | WS_VISIBLE | PBS_SMOOTH, CRect(0, 0, 400, 50), this, IDC_PROGRESS);
        m_progctrl.SetRange(0, 100);
        m_progctrl.SetWindowText(wndname);
        //绑定进度条到threadfunc,抽象出逻辑使在其内部动态更新进度条
        boost::packaged_task<bool> pt(boost::bind(threadfunc, paramdata, m_progctrl.m_hWnd));
        boost::unique_future<bool> uf = pt.get_future();
        boost::thread(boost::move(pt));
        uf.wait();
        if (uf.get())
                SetDlgItemText(IDC_STATU, "操作成功!");
        else
                SetDlgItemText(IDC_STATU, "操作失败!");
}

char toformat;

void CFasterDNSDlg::OnLvnGetdispinfoIplist(NMHDR *pNMHDR, LRESULT *pResult)
{//刷新数据
        NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
        // TODO:在此添加控件通知处理程序代码
        int index = pDispInfo->item.iItem;
        if (dataarray.size() == 0 || index > dataarray.size() - 1)
                return;
        testSpeedData& cur = dataarray;
        switch (pDispInfo->item.iSubItem)
        {
        case COL_IP:
                pDispInfo->item.pszText = (char*)cur.ip.c_str();
                break;
        case COL_LOC:
                pDispInfo->item.pszText = (char*)cur.location.c_str();
                break;
        case COL_RES:
                if (cur.responsetime == 0)
                        pDispInfo->item.pszText = "未测速";
                else if (cur.testtime == cur.failtime)
                        pDispInfo->item.pszText = "测速失败";
                else
                {
                        sprintf_s(toformat, "%d ms", cur.responsetime / (cur.testtime - cur.failtime));
                        pDispInfo->item.pszText = toformat;
                }
                break;
        case COL_FAIL:
                if (dataarray.testtime == 0)
                        pDispInfo->item.pszText = "未测速";
                else
                {
                        sprintf_s(toformat, "%d/%d", cur.failtime, cur.testtime);
                        pDispInfo->item.pszText = toformat;
                }
                break;
        }
        *pResult = 0;
}

void CFasterDNSDlg::OnAbout()
{
        AfxMessageBox("该程序在‘彗星DNS优化器’基础上修改得到,增加了数据库,有望未来支持ipv6\r\n作者:lichao890427 qq:571652571");
}

void CFasterDNSDlg::OnSetdns()
{//显示网卡窗口
        std::vector<std::string> selip;
        int uSelectedCount = m_list->GetSelectedCount();
        int nItem = -1;
        if (uSelectedCount > 0)
        {
                for (int i = 0; i < uSelectedCount; i++)
                {
                        nItem = m_list->GetNextItem(nItem, LVNI_SELECTED);
                        selip.push_back(dataarray.ip);
                }
                boost::thread(boost::bind(&CFasterDNSDlg::DoDNSConnection, this));
        }

        CSetDnsDlg setdns(selip);
        setdns.DoModal();
}

bool CompareIP(testSpeedData& lParam1, testSpeedData& lParam2)
{
        using namespace boost::asio;
        ip::address& addr1 = ip::address::from_string(lParam1.ip);
        ip::address& addr2 = ip::address::from_string(lParam2.ip);
        if (addr1.is_v4())
        {
                if (addr2.is_v4())
                {
                        return addr1.to_v4().to_ulong() < addr2.to_v4().to_ulong();
                }
                else
                        return true;
        }
        else
        {
                return false;
        }
}

bool CompareLOC(testSpeedData& lParam1, testSpeedData& lParam2)
{
        return lParam1.location < lParam2.location;
}

bool CompareRES(testSpeedData& lParam1, testSpeedData& lParam2)
{
        if (lParam1.failtime || lParam1.lefttime)
                return true;
        else if (lParam2.failtime || lParam2.lefttime)
                return false;
        else if (!lParam1.testtime || !lParam2.testtime)
                return lParam1.testtime < lParam2.testtime;
        else
                return lParam1.responsetime / lParam1.testtime < lParam2.responsetime / lParam2.testtime;
}

void CFasterDNSDlg::DoSort(bool(*f)(testSpeedData&, testSpeedData&))
{
        if (issorting)
        {
                AfxMessageBox("排序尚未完成!");
                return;
        }

        boost::mutex::scoped_lock mdata(datamutex);
        SetDlgItemText(IDC_STATU, "正在排序");
        issorting = true;
        std::sort(dataarray.begin(), dataarray.end(), f);
        for (int i = 0; i < dataarray.size(); i++)
        {
                LVITEM item = { 0 };
                item.mask = LVIF_TEXT;
                item.iItem = i;
                item.pszText = LPSTR_TEXTCALLBACK;
                m_list->SendMessage(LVM_SETITEMTEXT, i, (LPARAM)&item);
        }
        SetDlgItemText(IDC_STATU, "排序完毕");
        issorting = false;
}

void CFasterDNSDlg::OnHdnItemclickIplist(NMHDR *pNMHDR, LRESULT *pResult)
{//排序
        LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

        switch (phdr->iItem)
        {//不要直接修改listview,而是先修改和listview绑定的data,再通知listview
                case COL_IP:
                        boost::thread(boost::bind(&CFasterDNSDlg::DoSort, this, CompareIP));
                        break;
                case COL_LOC:
                        boost::thread(boost::bind(&CFasterDNSDlg::DoSort, this, CompareLOC));
                        break;
                case COL_RES:
                        boost::thread(boost::bind(&CFasterDNSDlg::DoSort, this, CompareRES));
                        break;
                case COL_FAIL:
                        break;
        }
        *pResult = 0;
}

void CFasterDNSDlg::OnNMRClickIplist(NMHDR *pNMHDR, LRESULT *pResult)
{//右键弹出菜单
        LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
        CMenu menu;
        menu.LoadMenu(IDR_POPUPMENU);
        CMenu* pPopup = menu.GetSubMenu(0);
        POINT pt;
        GetCursorPos(&pt);
        pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, this);
        *pResult = 0;
}

void CFasterDNSDlg::OnDeldns()
{//删除dns,先从数据库中删,再重新加载数据
        int uSelectedCount = m_list->GetSelectedCount();
        int nItem = -1;
        if (uSelectedCount > 0)
        {
                boost::mutex::scoped_lock mdata(datamutex);
                std::vector<std::string> temp;
                for (int i = 0; i < uSelectedCount; i++)
                {
                        nItem = m_list->GetNextItem(nItem, LVNI_SELECTED);
                        temp.push_back(dataarray.ip);
                }
                dodeldata(&temp, m_list->m_hWnd);
                dataarray.clear();
                m_list->DeleteAllItems();
                boost::thread(boost::bind(getdata, &dataarray, m_list->m_hWnd, GetDlgItem(IDC_STATU)->m_hWnd, &datamutex));
        }
}

std::set<std::string> resolvedip;
std::string domain="www.microsoft.com";

void testFunc(int index, std::vector<testSpeedData>* rawdata, HWND listview)
{
        testSpeedData& curdata = (*rawdata).at(index);
        std::vector<uint8_t> bufferdata;
        bool got = false;
        while (curdata.lefttime)
        {
                makedns(bufferdata, domain);
                int originlen = bufferdata.size();//发送包大小,用于定位返回answer
                replaceXid(bufferdata, rand() & 0xFFFF);
                uint32_t usedtime = curdata.timeout;
                if (!dodnsconnect(curdata.ip, usedtime, bufferdata))
                        curdata.failtime++;
                else
                {
                        curdata.responsetime += usedtime;
                        if (!got)
                        {//解析返回包
                                resolveAnswer(bufferdata, resolvedip, originlen);
                                got = true;
                        }
                }       
                curdata.lefttime--;
        }
        //刷新listview
        LVITEM item = { 0 };
        item.mask = LVIF_TEXT;
        item.iItem = index;
        item.pszText = LPSTR_TEXTCALLBACK;
        SendMessage(listview, LVM_SETITEMTEXT, index, (LPARAM)&item);
}

void CFasterDNSDlg::OnTimer(UINT_PTR nIDEvent)
{
        char status;
        sprintf_s(status,"%06d/%06d/%06d", task.size(), maxtask, dataarray.size());
        SetDlgItemText(IDC_TESTPROG, status);
        CDialogEx::OnTimer(nIDEvent);
}

void CFasterDNSDlg::DoDNSConnection()
{//设置testSpeedData
        maxtask = task.size();
        CString domaina;
        GetDlgItemText(IDC_DOMAIN, domaina);
        ::domain = (LPCTSTR)domaina;
        resolvedip.clear();
        ThreadPool<testSpeedData> newtaskset(taskmutex);
        newtaskset.Attach(threadnum, &task, &dataarray,m_list->m_hWnd);
        newtaskset.Exec(testFunc);
        OnBnClickedViewip();
}

void CFasterDNSDlg::InitOne(testSpeedData& obj)
{//初始化单个数据
        obj.failtime = 0;
        obj.lefttime = repeattime;
        obj.responsetime = 0;
        obj.testtime = repeattime;
        obj.timeout = timeout;
}

void CFasterDNSDlg::OnBnClickedAllinone()
{
        boost::mutex::scoped_lock mtask(taskmutex);
        //list和data绑定,数据更改通过data更新list而不直接操作list,因此该锁同时绑定data和list
        if (!task.empty())
        {
                AfxMessageBox("测试尚未结束,请先停止测试");
                return;
        }
        int nCount = m_list->GetItemCount();
        task.clear();
        for (int i = 0; i < nCount; i++)
        {
                task.push_back(i);
        }
        boost::thread(boost::bind(&CFasterDNSDlg::DoDNSConnection, this));
}

void CFasterDNSDlg::OnBnClickedStart()
{//测试选中
        boost::mutex::scoped_lock mtask(taskmutex);
        if (!task.empty())
        {
                AfxMessageBox("测试尚未结束,请先停止测试");
                return;
        }
        int uSelectedCount = m_list->GetSelectedCount();
        int nItem = -1;
        if (uSelectedCount > 0)
        {
                task.clear();
                for (int i = 0; i < uSelectedCount; i++)
                {
                        nItem = m_list->GetNextItem(nItem, LVNI_SELECTED);
                        InitOne(dataarray);
                        task.push_back(nItem);
                }
                boost::thread(boost::bind(&CFasterDNSDlg::DoDNSConnection, this));
        }
}

void CFasterDNSDlg::OnBnClickedStop()
{
        //停止当前任务意味着清除剩余分配任务task
        boost::mutex::scoped_lock mio(taskmutex);
        //使用同一个锁保证不和分配任务线程操作冲突
        task.clear();
}

void CFasterDNSDlg::OnBnClickedViewip()
{
        CShowIp ipdlg(domain, resolvedip);
        ipdlg.DoModal();
}

void CFasterDNSDlg::OnAdddns()
{
        OnBnClickedAddDNS();
}

void CFasterDNSDlg::OnModify()
{
        CGlobalSetting settings(threadnum, timeout, repeattime);
        settings.DoModal();
}

void CFasterDNSDlg::OnStartall()
{
        OnBnClickedAllinone();
}

void CFasterDNSDlg::OnStopall()
{
        OnBnClickedStop();
}

void CFasterDNSDlg::OnTestip()
{
        OnBnClickedViewip();
}

void CFasterDNSDlg::OnExit()
{
        SendMessage(WM_CLOSE, 0, 0);
}

void CFasterDNSDlg::OnAllinone()
{
        OnBnClickedAllinone();
}

void CFasterDNSDlg::OnStart()
{
        OnBnClickedStart();
}

void CFasterDNSDlg::OnStop()
{
        OnBnClickedStop();
}


functions.cpp
#include "stdafx.h"

#include <boost/function.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/system/error_code.hpp>
#include <vector>
#include <set>
#include <winsock.h>
#include <stdint.h>
#include <iphlpapi.h>
#include <windows.h>
#include "functions.h"
#include "sqlite3.h"
#pragma comment(lib,"sqlite3.lib")
#pragma comment(lib,"iphlpapi.lib")
/************************************************************************/
/* 单例模式获取实例                                                   */
/************************************************************************/
std::vector<testSpeedData>* ipcontainer::testdata = NULL;
int* ipcontainer::pcount = NULL;
HWND ipcontainer::pwnd = NULL;

ipcontainer& ipcontainer::getInstance()
{
        boost::mutex mio;
        boost::mutex::scoped_lock lock(mio);
        static ipcontainer container;
        return container;
}

/************************************************************************/
/* 向数据库中增加dns数据
        ip:待添加dns服务器ip地址(非域名)        addr:待添加dns服务器地理位置        */
/************************************************************************/
bool ipcontainer::adddata(const std::string& ip, const std::string& addr)
{
        int status = SQLITE_OK;
        char* zErrMsg = NULL;
        std::string toadd = "insert into dnss values ('" + ip + "','" + addr + "')";
        try
        {
                status = sqlite3_exec(db, toadd.c_str(), NULL, NULL, &zErrMsg);
                if (status != SQLITE_OK)
                        throw "Add failed!";
        }
        catch (...)
        {
                return false;
        }
        return true;
}

/************************************************************************/
/* 从数据库中删除dns数据
        ip:待删除dns服务器ip地址(非域名)                                                                        */
/************************************************************************/
bool ipcontainer::deldata(const std::string& ip)
{
        int status = SQLITE_OK;
        char* zErrMsg = NULL;
        std::string toadd = "delete from dnss where ipaddr = '" + ip + "'";
        try
        {
                status = sqlite3_exec(db, toadd.c_str(), NULL, NULL, &zErrMsg);
                if (status != SQLITE_OK)
                        throw "Del failed!";
        }
        catch (...)
        {
                return false;
        }
        return true;
}

/************************************************************************/
/* 获取dns数据总入口
        dataparam:存放获得数据结果                                                                                        */
/************************************************************************/
bool ipcontainer::getdata(std::vector<testSpeedData>* dataparam, HWND listctrl)
{
        try
        {
                ipcontainer::testdata = dataparam;
                ipcontainer::pwnd = listctrl;
                int status = SQLITE_OK;
                char* zErrMsg = NULL;
                status = sqlite3_exec(db, "select * from dnss", getdatacallback, NULL, &zErrMsg);
                if (status != SQLITE_OK)
                        throw "Get failed!";
        }
        catch (...)
        {
                ipcontainer::testdata = NULL;
                ipcontainer::pwnd = NULL;
                return false;
        }
        ipcontainer::testdata = NULL;
        ipcontainer::pwnd = NULL;
        return true;
}

/************************************************************************/
/* 获取dns数据记录总数                                                                    */
/************************************************************************/
bool ipcontainer::getcount(int& count)
{
        try
        {
                ipcontainer::pcount = &count;
                int status = SQLITE_OK;
                char* zErrMsg = NULL;
                status = sqlite3_exec(db, "select count(*) from dnss", getcountcallback, NULL, &zErrMsg);
                if (status != SQLITE_OK)
                        throw "Get failed!";
        }
        catch (...)
        {
                ipcontainer::pcount = NULL;
                return false;
        }
        ipcontainer::pcount = NULL;
        return true;
}

/************************************************************************/
/* 析构时关闭数据库                                                   */
/************************************************************************/
ipcontainer::~ipcontainer()
{
        ipcontainer::testdata = NULL;
        ipcontainer::pcount = NULL;
        ipcontainer::pwnd = NULL;
        sqlite3_close(db);
        db = NULL;
}

/************************************************************************/
/* 构造函数打开数据库                                                                                                        */
/************************************************************************/
ipcontainer::ipcontainer()
{
        int status = SQLITE_OK;
        db = NULL;
        status = sqlite3_open(DATABASE, &db);
        if (status != SQLITE_OK)
                throw "Open failed!";
}

/************************************************************************/
/* 获取记录数据数组的回调函数,用于获取记录数据数组
        argc:获得条目个数=2                argv:ip                        argv:location                        */
/************************************************************************/
int ipcontainer::getdatacallback(void *NotUsed, int argc, char **argv, char **azColName)
{
        LVITEM item = { 0 };
        item.mask = LVIF_TEXT;
        item.iItem = ipcontainer::testdata->size();
        item.lParam = item.iItem;
        item.pszText = LPSTR_TEXTCALLBACK;
        ipcontainer::testdata->push_back(testSpeedData(argv, argv));
        SendMessage(pwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
        return 0;
}

/************************************************************************/
/* 获取记录条目的回调函数,用于得到记录条目   
        argc:获得条目个数=1                argv:记录条目                                                        */
/************************************************************************/
int ipcontainer::getcountcallback(void *NotUsed, int argc, char **argv, char **azColName)
{
        try
        {
                *ipcontainer::pcount = boost::lexical_cast<int>(argv);
        }
        catch (...)
        {
                *ipcontainer::pcount = 0;
        }
        return 0;
}

/************************************************************************/
/* 增加dns数据总入口
setpos:设置进度显示回调函数                dataparam:要添加的数据阵列*/
/************************************************************************/
bool doadddata(dbData* dataparam, HWND progctrl)
{
        int size = dataparam->size() / 100;
        int i = 0, j = 0;
        SendMessage(progctrl, PBM_SETPOS, 0, 0);
        try
        {
                dbData::const_iterator itor = dataparam->begin();
                ipcontainer& container=ipcontainer::getInstance();
                while (itor != dataparam->end())
                {
                        container.adddata(itor->first, itor->second);
                        ++itor;
                        ++i;
                        if (i >= size)
                        {
                                i = 0;
                                SendMessage(progctrl, PBM_SETPOS, ++j, 0);
                        }
                }
        }
        catch (...)
        {
                //发生错误
                return false;
        }
        return true;
}

/************************************************************************/
/* 删除dns数据总入口
setpos:设置进度显示回调函数                dataparam:要删除的数据阵列*/
/************************************************************************/
bool dodeldata(std::vector<std::string>* dataparam, HWND progctrl)
{
        int size = dataparam->size() / 100;
        int i = 0, j = 0;
        SendMessage(progctrl, PBM_SETPOS, 0, 0);
        try
        {
                std::vector<std::string>::iterator itor = dataparam->begin();
                ipcontainer& container = ipcontainer::getInstance();
                while (itor != dataparam->end())
                {
                        container.deldata(*itor);
                        ++itor;
                        ++i;
                        if (i >= size)
                        {
                                i = 0;
                                SendMessage(progctrl, PBM_SETPOS, ++j, 0);
                        }
                }
        }
        catch (...)
        {
                //发生错误
                return false;
        }
        return true;
}

/************************************************************************/
/* 尝试http连接
        ip:要测试连通性的地址                timeout:超时返回                                                */
/************************************************************************/
bool dohttpconnect(const std::string& ip,uint32_t& timeout)
{//ip不能是域名 timeout同时用于设置超时和计时
        using namespace boost::asio;
        using namespace boost::posix_time;
        try
        {
                tcpclient c;
                boost::system::error_code ec;
                setsockopt(c.socket_.native(), SOL_SOCKET, SO_RCVTIMEO, (const char*)timeout, sizeof(timeout));
                ip::tcp::endpoint ep(ip::address::from_string(ip), PORT_HTTP);
                ptime ptStart = microsec_clock::local_time();
                c.connect(ep, boost::posix_time::millisec(timeout), ec);
                if (ec.value())
                        throw "error";
                ptime ptEnd = microsec_clock::local_time();
                timeout = (int32_t)(ptEnd - ptStart).total_milliseconds();
        }
        catch (...)
        {
                return false;
        }
        return true;
}

/************************************************************************/
/* 尝试dns连接
        ip:要测试连通性的地址                timeout:超时返回               
        bufferdata:用于发送和接收数据                                                                                */
/************************************************************************/
bool dodnsconnect(const std::string& ip, uint32_t& timeout,std::vector<uint8_t>& bufferdata)
{//bufferdata用于输入和输出 ip为服务器地址
        using namespace boost::asio;
        using namespace boost::posix_time;
        try
        {
                udpclient c(ip::udp::endpoint(ip::udp::v4(), rand() & 0x7FFF + 0x8000));
                boost::system::error_code ec;
                setsockopt(c.socket_.native(), SOL_SOCKET, SO_RCVTIMEO, (const char*)timeout, sizeof(timeout));
                setsockopt(c.socket_.native(), SOL_SOCKET, SO_BROADCAST, "\0\0\0\0", 4);
                ip::udp::endpoint ep(ip::address::from_string(ip), PORT_DNS);
                c.socket_.send_to(buffer((bufferdata)),ep);
                bufferdata.clear();
                bufferdata.resize(MAXS_RECVNUM);
                ptime ptStart = microsec_clock::local_time();
                c.receive(buffer(bufferdata), boost::posix_time::millisec(timeout), ec);
                if (ec.value())
                        throw "error";
                ptime ptEnd = microsec_clock::local_time();
                timeout = (int32_t)(ptEnd - ptStart).total_milliseconds();
        }
        catch (...)
        {
                return false;
        }
        return true;
}

/************************************************************************/
/* 构造dns数据包
        bufferdata:用于存储构造数据包结果
        testdomain:用于验证的域名,不能用ip地址                                                                */
/************************************************************************/
void makedns(std::vector<uint8_t>& bufferdata, const std::string& testdomain)
{//testip为验证ip,此函数用于testip更换时;Xid更换时用replaceXid
        bufferdata.resize(sizeof(DNS_HEADER));
        DNS_HEADER* pheader = (DNS_HEADER*)bufferdata.data();
        memset(pheader, 0, sizeof(DNS_HEADER));
        pheader->RecursionDesired = 1;
        pheader->QuestionCount = 1;//查询一个域名
        DNS_BYTE_FLIP_HEADER_COUNTS(pheader);
        boost::asio::ip::address addr;
        spliter splitvec;
        boost::split(splitvec, testdomain, boost::is_any_of("."));
        for (spliter::iterator itor = splitvec.begin(); itor != splitvec.end(); ++itor)
        {
                bufferdata.push_back((*itor).length());
                bufferdata.insert(bufferdata.end(), (*itor).begin(),(*itor).end());
        }
        uint8_t tailer = { 0x00, 0x00, 0x01, 0x00, 0x01 };
        bufferdata.insert(bufferdata.end(), tailer, tailer+SIZE_DNSTAILER);
}

/************************************************************************/
/* 修改dns数据包的TransactionID,考虑优化使用
        bufferdata:待修改数据                Xid:新的TransactionID                                */
/************************************************************************/
void replaceXid(std::vector<uint8_t>& bufferdata, uint16_t Xid)
{
        ((DNS_HEADER*)bufferdata.data())->Xid = htons(Xid);
}

/************************************************************************/
/*从返回包结果中解析获取到的地址   
        bufferdata:服务器返回的待解析数据        resolveip:存储结果
        originlen:发送包大小*/
/************************************************************************/
void resolveAnswer(std::vector<uint8_t>& bufferdata, std::set<std::string>& resolvedip, int originlen)
{
        DNS_HEADER* pheader = (DNS_HEADER*)bufferdata.data();
        DNS_BYTE_FLIP_HEADER_COUNTS(pheader);
        uint8_t* ptr = (uint8_t*)pheader + originlen;
        for (int i = 0; i < pheader->AnswerCount; i++)
        {
                DNSANSWER_HEADER* aheader = (DNSANSWER_HEADER*)ptr;
                DNS_BYTE_FLIP_ANSWERHEADER_COUNTS(aheader);
                if(aheader->Type == 1)//A:host address
                {
                        BYTE* cdata = (BYTE*)aheader + sizeof(DNSANSWER_HEADER);
                        if (aheader->Datalength == 4)//ipv4
                        {
                                char temp;
                                sprintf_s(temp, "%d.%d.%d.%d", cdata, cdata, cdata, cdata);
                                resolvedip.insert(std::string(temp));
                        }
                        else if (aheader->Datalength == 6)//ipv6
                        {
                                //v6的没有条件研究呢。。。
                        }
                }
                ptr += aheader->Datalength + sizeof(DNSANSWER_HEADER);
        }
}

/************************************************************************/
/* 获取网卡适配器
        interfaces:存储结果                                                                                                        */
/************************************************************************/
bool getinterface(std::vector<std::string>& interfaces)
{
        DWORD dwRetVal = 0;
        ULONG outBufLen = 15000;
        LPVOID lpMsgBuf = NULL;
        PIP_ADAPTER_ADDRESSES pAddress = NULL;
        interfaces.clear();
        do
        {
                pAddress = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, outBufLen);
                if (pAddress == NULL)
                        return false;
                dwRetVal = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddress, &outBufLen);
                if (dwRetVal == ERROR_BUFFER_OVERFLOW)
                {
                        HeapFree(GetProcessHeap(), 0, pAddress);
                        pAddress = NULL;
                }
        } while (dwRetVal == ERROR_BUFFER_OVERFLOW);
        if (dwRetVal != NO_ERROR)
                return false;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddress;
        while (pCurrAddresses)
        {
                HKEY hkResult;
                std::string query = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
                query += pCurrAddresses->AdapterName;
                query += "\\Connection\\";
                dwRetVal = RegOpenKey(HKEY_LOCAL_MACHINE, query.c_str(), &hkResult);
                if (dwRetVal == ERROR_SUCCESS)
                {
                        char buffer;
                        LONG cbData = 256;
                        dwRetVal = RegQueryValue(hkResult, "Name", buffer, &cbData);
                        if (dwRetVal == ERROR_SUCCESS)
                        {
                                interfaces.push_back((char*)buffer);
                        }
                }
                pCurrAddresses = pCurrAddresses->Next;
        }

        if (pAddress)
                HeapFree(GetProcessHeap(), 0, pAddress);
        return true;
}

/************************************************************************/
/* 设置指定网卡适配器dns
        setpos:设置进度显示回调函数                interfaces:待设置适配器               
        address为点分十进制地址                                                                                                */
/************************************************************************/
bool setinterface(std::vector<std::string>& interfaces, std::vector<std::string>& addresss, HWND progctrl)
{
        using namespace boost::asio;
        STARTUPINFO StartupInfo = { 0 };
        PROCESS_INFORMATION ProcessInfo = { 0 };
        StartupInfo.cb = sizeof(STARTUPINFO);
        StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
        StartupInfo.wShowWindow = SW_HIDE;
        std::string cmd;
        int count = 0;
        SendMessage(progctrl, PBM_SETPOS, 0, 0);
        for (std::vector<std::string>::iterator itori = interfaces.begin(); itori != interfaces.end(); ++itori)
        {
                BOOL bRet;
                cmd = "netsh interface ipv4 set dns name=\"" + *itori + "\" source=static addr=none";
                //清除DNS设置       
                bRet=CreateProcess(NULL, (char*)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
                if (!bRet)
                        return false;
                if (ProcessInfo.hProcess)
                        WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
                cmd = "netsh interface ipv6 set dns name=\"" + *itori + "\" source=static addr=none";
                bRet = CreateProcess(NULL, (char*)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
                if (!bRet)
                        return false;
                if (ProcessInfo.hProcess)
                        WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
                SendMessage(progctrl, PBM_SETPOS, int(100 * (float)count++ / interfaces.size()), 0);
                SetWindowText(progctrl, ("正在清除设置 " + *itori).c_str());
                for (std::vector<std::string>::iterator itora = addresss.begin(); itora != interfaces.end(); ++itora)
                {
                        if ((ip::address::from_string(*itora)).is_v4())
                                cmd = "netsh interface ipv4 add dns name=\"" + *itori + "\" addr=" + *itora;
                        else
                                cmd = "netsh interface ipv6 add dns name=\"" + *itori + "\" addr=" + *itora;
                        SetWindowText(progctrl, ("正在设置 " + *itora).c_str());
                        bRet = CreateProcess(NULL, (char*)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
                        if (!bRet)
                                return false;
                        if (ProcessInfo.hProcess)
                                WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
                }
        }
        return true;
}

/************************************************************************/
/* 封装getcount                                                         */
/************************************************************************/
bool getcount(int& count)
{
        try
        {
                ipcontainer::getInstance().getcount(count);
        }
        catch (...)
        {
                return false;
        }
        return true;
}

/************************************************************************/
/* 封装getdata                                                          */
/************************************************************************/
bool getdata(std::vector<testSpeedData>* dataparam, HWND listctrl, HWND statu, boost::mutex* mu)
{
        boost::mutex::scoped_lock mdata(*mu);
        SetWindowText(statu, "正在初始化数据!");
        try
        {
                ipcontainer::getInstance().getdata(dataparam, listctrl);
        }
        catch (...)
        {
                return false;
        }
        SetWindowText(statu, "初始化完毕!");
        return true;
}

元始天尊 发表于 2015-3-9 09:30:37

完整工程:http://pan.baidu.com/s/1dDrjRDB
页: [1]
查看完整版本: 我的新版dns加速器出炉啦!!!欢迎提出意见和建议