找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3454|回复: 1

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

[复制链接]
发表于 2015-3-8 15:20:53 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

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

重要代码:
functions.h
  1. #pragma once
  2. #ifndef FASTERDNS_COMMONHEADER
  3. #define FASTERDNS_COMMONHEADER
  4. #endif

  5. #include <string>
  6. #include <vector>
  7. #include <boost/asio.hpp>
  8. #include <boost/function.hpp>
  9. #include <boost/thread/mutex.hpp>
  10. #include <boost/thread.hpp>
  11. #include <boost/thread/detail/thread_group.hpp>
  12. #include <deque>
  13. #include <set>
  14. #include "sqlite3.h"

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

  17. class testSpeedData//每轮测试所用数据
  18. {
  19. public:
  20.         testSpeedData(char* _ip, char* _location) :ip(_ip), location(_location)
  21.         {
  22.                 responsetime = 0;
  23.                 testtime = 0;
  24.                 lefttime = 0;
  25.                 failtime = 0;
  26.                 timeout = 0;
  27.         }
  28. public:
  29.         std::string ip;//DNS地址
  30.         std::string location;//所在地
  31.         int responsetime;//总响应时间
  32.         int testtime;//总测试次数
  33.         int lefttime;//剩余次数
  34.         int failtime;//失败次数
  35.         int timeout;//超时时间
  36. };

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

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


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

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

  54. enum
  55. {
  56.         //解析CSV数据文件
  57.         CSV_IP = 0,
  58.         CSV_NAME,
  59.         CSV_COUNTRYID,
  60.         CSV_CITY,
  61.         CSV_MAX,
  62.         //解析普通数据文件
  63.         COM_IP = 0,
  64.         COM_LOCATION,
  65.         COM_MAX,
  66.         //端口
  67.         PORT_HTTP = 80,
  68.         PORT_DNS = 53,
  69.         //DNS包
  70.         SIZE_DNSHEADER = sizeof(DNS_HEADER),
  71.         SIZE_DNSTAILER = 5,
  72.         //值域
  73.         INIT_THREADNUM = 1,
  74.         LOW_THREADNUM = 0,
  75.         HIGH_THREADNUM = 1000,
  76.         INIT_TIMEOUT = 1000,
  77.         LOW_TIMEOUT = 10,
  78.         HIGH_TIMEOUT = 10000,
  79.         INIT_TESTNUM = 1,
  80.         LOW_TESTNUM = 0,
  81.         HIGH_TESTNUM = 100,
  82.         //显示列
  83.         COL_IP = 0,
  84.         COL_LOC,
  85.         COL_RES,//平均响应时间
  86.         COL_FAIL,//失败次数/总次数
  87.         //其他
  88.         IDC_PROGRESS = 12345,
  89.         MAX_DOMAIN_LENGTH = 256,
  90.         MAXS_RECVNUM = 65536,
  91.         HTTP_CONNECTTIME = 5000,
  92.         TIMER1_ID=10000,
  93. };

  94. class ipcontainer:public boost::noncopyable
  95. {
  96. public:
  97.         static ipcontainer& getInstance();
  98.         bool adddata(const std::string& ip, const std::string& addr);
  99.         bool deldata(const std::string& ip);
  100.         bool getdata(std::vector<testSpeedData>* dataparam,HWND listctrl);
  101.         bool getcount(int& pcount);
  102.         virtual ~ipcontainer();
  103. private:
  104.         ipcontainer();
  105.         static int getdatacallback(void *NotUsed, int argc, char **argv, char **azColName);
  106.         static int getcountcallback(void *NotUsed, int argc, char **argv, char **azColName);
  107. private:
  108.         sqlite3* db;
  109.         static int* pcount;
  110.         static std::vector<testSpeedData>* testdata;
  111.         static HWND pwnd;
  112. };

  113. template<typename D>
  114. class ThreadPool
  115. {
  116. public:
  117.         ThreadPool(boost::mutex& _mu) :mu(_mu)
  118.         {
  119.                 threadnum = 0;
  120.                 task = NULL;
  121.         }

  122.         virtual ~ThreadPool()
  123.         {
  124.                 if (ppio)
  125.                 {
  126.                         for (int i = 0; i < threadnum; i++)
  127.                                 delete ppio[i];
  128.                         delete[]ppio;
  129.                 }
  130.         }

  131.         bool Attach(int _threadnum, std::deque<int>* _task, std::vector<D>* _dataarray, HWND _listview)
  132.         {
  133.                 if (!_task || _task->empty() || !_dataarray)
  134.                         return false;//任务未结束
  135.                 task = _task;
  136.                 dataarray = _dataarray;
  137.                 threadnum = _threadnum;
  138.                 listview = _listview;
  139.                 ppio = new boost::asio::io_service*[threadnum];
  140.                 if (!ppio)
  141.                         return false;
  142.                 for (int i = 0; i < threadnum; i++)
  143.                 {
  144.                         ppio[i] = new boost::asio::io_service;
  145.                         if (!ppio[i])//模拟new[]的行为,释放之前成功分配的内存
  146.                         {
  147.                                 for (int j = i-1; j >= 0; j--)
  148.                                         delete ppio[j];
  149.                                 delete[]ppio;
  150.                                 return false;
  151.                         }
  152.                 }
  153.                 return true;
  154.         }

  155.         bool Exec(void(*f)(int, std::vector<D>*, HWND))
  156.         {
  157.                 try
  158.                 {
  159.                         boost::thread_group tg;
  160.                         //建立线程组
  161.                         for (int i = 0; i < threadnum; i++)
  162.                         {
  163.                                 tg.create_thread(boost::bind(&ThreadPool::wrapper, this, ppio[i],f));
  164.                         }
  165.                         //等待所有任务执行完毕
  166.                         tg.join_all();
  167.                 }
  168.                 catch (...)
  169.                 {
  170.                         //确保释放new
  171.                         return false;
  172.                 }
  173.                 return true;
  174.         }

  175. private:
  176.         //用于将task里的任务分配各给threadnum个活动线程,分配时要进行线程同步
  177.         void wrapper(boost::asio::io_service* service, void(*f)(int, std::vector<D>*, HWND))
  178.         {
  179.                 while (true)
  180.                 {
  181.                         mu.lock();
  182.                         if (task->empty())
  183.                         {
  184.                                 mu.unlock();
  185.                                 return;
  186.                         }
  187.                         service->post(boost::bind(f, task->front(), dataarray, listview));
  188.                         task->pop_front();
  189.                         mu.unlock();
  190.                         service->run();
  191.                         service->reset();
  192.                 }
  193.         }

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

  202. #pragma pack(push)
  203. #pragma pack(2)
  204. typedef struct _DNSANSWER_HEADER
  205. {
  206.         WORD Name;
  207.         WORD Type;
  208.         WORD Class;
  209.         DWORD Timetolive;
  210.         WORD Datalength;
  211. }DNSANSWER_HEADER, *PDNSANSWER_HEADER;
  212. #pragma pack(pop)

  213. #define DNS_BYTE_FLIP_ANSWERHEADER_COUNTS(pHeader)\
  214.         {\
  215.         PDNSANSWER_HEADER _head = (pHeader); \
  216.         INLINE_HTONS(_head->Name,                _head->Name);\
  217.         INLINE_HTONS(_head->Type,                _head->Type); \
  218.         INLINE_HTONS(_head->Class,                _head->Class); \
  219.         INLINE_HTONS(_head->Timetolive, _head->Timetolive); \
  220.         INLINE_HTONS(_head->Datalength, _head->Datalength); \
  221.         }

  222. class udpclient//只为做超时处理
  223. {
  224. public:
  225.         udpclient(const boost::asio::ip::udp::endpoint& listen_endpoint) :socket_(io_service_, listen_endpoint), deadline_(io_service_)
  226.         {
  227.                 deadline_.expires_at(boost::posix_time::pos_infin);
  228.                 check_deadline();
  229.         }
  230.         std::size_t receive(const boost::asio::mutable_buffer& buffer, boost::posix_time::time_duration timeout, boost::system::error_code& ec)
  231.         {
  232.                 deadline_.expires_from_now(timeout);
  233.                 ec = boost::asio::error::would_block;
  234.                 std::size_t length = 0;
  235.                 socket_.async_receive(boost::asio::buffer(buffer), boost::bind(&udpclient::handle_receive, _1, _2, &ec, &length));
  236.                 do io_service_.run_one(); while (ec == boost::asio::error::would_block);
  237.                 return length;
  238.         }
  239. private:
  240.         void check_deadline()
  241.         {
  242.                 if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
  243.                 {
  244.                         socket_.cancel();
  245.                         deadline_.expires_at(boost::posix_time::pos_infin);
  246.                 }
  247.                 deadline_.async_wait(boost::bind(&udpclient::check_deadline, this));
  248.         }
  249.         static void handle_receive(const boost::system::error_code& ec, std::size_t length,
  250.                 boost::system::error_code* out_ec, std::size_t* out_length)
  251.         {
  252.                 *out_ec = ec;
  253.                 *out_length = length;
  254.         }
  255. private:
  256.         boost::asio::io_service io_service_;
  257.         boost::asio::deadline_timer deadline_;
  258. public:
  259.         boost::asio::ip::udp::socket socket_;
  260. };

  261. class tcpclient//只为做超时处理
  262. {
  263. public:
  264.         tcpclient() :socket_(io_service_), deadline_(io_service_)
  265.         {
  266.                 deadline_.expires_at(boost::posix_time::pos_infin);
  267.                 check_deadline();
  268.         }
  269.         void connect(const boost::asio::ip::tcp::endpoint ep, boost::posix_time::time_duration timeout, boost::system::error_code& ec)
  270.         {
  271.                 deadline_.expires_from_now(timeout);
  272.                 ec = boost::asio::error::would_block;
  273.                 socket_.async_connect(ep,boost::bind(&tcpclient::handle_connect, _1, &ec));
  274.                 do io_service_.run_one(); while (ec == boost::asio::error::would_block);
  275.         }
  276. private:
  277.         void check_deadline()
  278.         {
  279.                 if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
  280.                 {
  281.                         socket_.cancel();
  282.                         deadline_.expires_at(boost::posix_time::pos_infin);
  283.                 }
  284.                 deadline_.async_wait(boost::bind(&tcpclient::check_deadline, this));
  285.         }
  286.         static void handle_connect(const boost::system::error_code& ec, boost::system::error_code* out_ec)
  287.         {
  288.                 *out_ec = ec;
  289.         }
  290. private:
  291.         boost::asio::io_service io_service_;
  292.         boost::asio::deadline_timer deadline_;
  293. public:
  294.         boost::asio::ip::tcp::socket socket_;
  295. };
复制代码


fasterdnsdlg.cpp

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

  3. #include "stdafx.h"
  4. #include "FasterDNS.h"
  5. #include "FasterDNSDlg.h"
  6. #include "SetDnsDlg.h"
  7. #include "afxdialogex.h"
  8. #include <boost/scoped_ptr.hpp>
  9. #include <boost/bind.hpp>
  10. #include <boost/thread.hpp>
  11. #include <boost/range.hpp>
  12. #include <boost/algorithm/string.hpp>
  13. #include <boost/xpressive/xpressive.hpp>
  14. #include <boost/asio.hpp>
  15. #include <boost/lexical_cast.hpp>
  16. #include <boost/format.hpp>
  17. #include <queue>
  18. #include <fstream>
  19. #include <set>
  20. #include "functions.h"
  21. #include <stdlib.h>
  22. #include "ShowIp.h"
  23. #include "GlobalSetting.h"

  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #endif

  27. CFasterDNSDlg::CFasterDNSDlg(CWnd* pParent /*=NULL*/)
  28.         : CDialogEx(CFasterDNSDlg::IDD, pParent)
  29. {
  30.         m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  31. }

  32. void CFasterDNSDlg::DoDataExchange(CDataExchange* pDX)
  33. {
  34.         CDialogEx::DoDataExchange(pDX);
  35. }

  36. BEGIN_MESSAGE_MAP(CFasterDNSDlg, CDialogEx)
  37.         ON_WM_PAINT()
  38.         ON_BN_CLICKED(IDC_ADDDNS, &CFasterDNSDlg::OnBnClickedAddDNS)
  39.         ON_NOTIFY(LVN_GETDISPINFO, IDC_IPLIST, &CFasterDNSDlg::OnLvnGetdispinfoIplist)
  40.         ON_COMMAND(ID_ABOUT, &CFasterDNSDlg::OnAbout)
  41.         ON_COMMAND(ID_SETDNS, &CFasterDNSDlg::OnSetdns)
  42.         ON_NOTIFY(HDN_ITEMCLICK, 0, &CFasterDNSDlg::OnHdnItemclickIplist)
  43.         ON_NOTIFY(NM_RCLICK, IDC_IPLIST, &CFasterDNSDlg::OnNMRClickIplist)
  44.         ON_COMMAND(ID_DELDNS, &CFasterDNSDlg::OnDeldns)
  45.         ON_BN_CLICKED(IDC_ALLINONE, &CFasterDNSDlg::OnBnClickedAllinone)
  46.         ON_BN_CLICKED(IDC_START, &CFasterDNSDlg::OnBnClickedStart)
  47.         ON_BN_CLICKED(IDC_STOP, &CFasterDNSDlg::OnBnClickedStop)
  48.         ON_BN_CLICKED(IDC_VIEWIP, &CFasterDNSDlg::OnBnClickedViewip)
  49.         ON_WM_TIMER()
  50.         ON_COMMAND(ID_ADDDNS, &CFasterDNSDlg::OnAdddns)
  51.         ON_COMMAND(ID_MODIFY, &CFasterDNSDlg::OnModify)
  52.         ON_COMMAND(ID_STARTALL, &CFasterDNSDlg::OnStartall)
  53.         ON_COMMAND(ID_STOPALL, &CFasterDNSDlg::OnStopall)
  54.         ON_COMMAND(ID_TESTIP, &CFasterDNSDlg::OnTestip)
  55.         ON_COMMAND(ID_EXIT, &CFasterDNSDlg::OnExit)
  56.         ON_COMMAND(ID_ALLINONE, &CFasterDNSDlg::OnAllinone)
  57.         ON_COMMAND(ID_START, &CFasterDNSDlg::OnStart)
  58.         ON_COMMAND(ID_STOP, &CFasterDNSDlg::OnStop)
  59. END_MESSAGE_MAP()

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

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

  83. void CFasterDNSDlg::OnPaint()
  84. {
  85.         if (IsIconic())
  86.         {
  87.                 CPaintDC dc(this); // 用于绘制的设备上下文
  88.                 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  89.                 int cxIcon = GetSystemMetrics(SM_CXICON);
  90.                 int cyIcon = GetSystemMetrics(SM_CYICON);
  91.                 CRect rect;
  92.                 GetClientRect(&rect);
  93.                 int x = (rect.Width() - cxIcon + 1) / 2;
  94.                 int y = (rect.Height() - cyIcon + 1) / 2;
  95.                 dc.DrawIcon(x, y, m_hIcon);
  96.         }
  97.         else
  98.         {
  99.                 CDialogEx::OnPaint();
  100.         }
  101. }

  102. void CFasterDNSDlg::OnBnClickedAddDNS()
  103. {
  104.         CFileDialog  dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "*.*", NULL);
  105.         if (IDOK == dlg.DoModal())
  106.         {
  107.                 //读取文件,解析出ip
  108.                 std::fstream file;
  109.                 std::string line;
  110.                 dbData toadd;
  111.                 boost::asio::ip::address addr;
  112.                 spliter splitvec;
  113.                 //获取大小
  114.                 file.open(dlg.GetPathName(), std::ios::in);
  115.                 file.seekg(0,std::ios::end);
  116.                 int totalsize = file.tellg();
  117.                 file.seekg(0,std::ios::beg);

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

  123.                 if (dlg.GetFileName() == CSVDATA)
  124.                 {
  125.                         getline(file, line);//跳过第一行
  126.                         while (!file.eof())
  127.                         {
  128.                                 int pos2 = file.tellg();
  129.                                 m_progctrl.SetPos(int(100*(double)file.tellg()/totalsize));
  130.                                 getline(file, line);
  131.                                 boost::split(splitvec, line, boost::is_any_of(","));
  132.                                 try
  133.                                 {
  134.                                         if (splitvec.size() < CSV_MAX)
  135.                                                 throw "Error";
  136.                                         addr = addr.from_string(splitvec[CSV_IP]);
  137.                                 }
  138.                                 catch (...)
  139.                                 {
  140.                                         break;
  141.                                 }
  142.                                 LVITEM item = { 0 };
  143.                                 item.mask = LVIF_TEXT;
  144.                                 item.iItem = dataarray.size();
  145.                                 item.lParam = item.iItem;
  146.                                 item.pszText = LPSTR_TEXTCALLBACK;
  147.                                 dataarray.push_back(testSpeedData((char*)splitvec[CSV_IP].c_str(), (char*)(splitvec[CSV_COUNTRYID] + " " + splitvec[CSV_CITY]).c_str()));
  148.                                 m_list->InsertItem(&item);
  149.                                 toadd.push_back(make_pair(splitvec[CSV_IP], splitvec[CSV_COUNTRYID] + " " + splitvec[CSV_CITY]));
  150.                         }
  151.                 }
  152.                 else
  153.                 {//普通文件,ip地址和位置信息用逗号分隔
  154.                         while (!file.eof())
  155.                         {
  156.                                 m_progctrl.SetPos(int(100*(double)file.tellg() / totalsize));
  157.                                 getline(file, line);
  158.                                 boost::split(splitvec, line, boost::is_any_of(","));
  159.                                 try
  160.                                 {
  161.                                         if (splitvec.size() < COM_MAX)
  162.                                                 throw "Error";
  163.                                         addr = addr.from_string(splitvec[COM_IP]);
  164.                                 }
  165.                                 catch (...)
  166.                                 {
  167.                                         break;
  168.                                 }
  169.                                 LVITEM item = { 0 };
  170.                                 item.mask = LVIF_TEXT;
  171.                                 item.iItem = dataarray.size();
  172.                                 item.lParam = item.iItem;
  173.                                 item.pszText = LPSTR_TEXTCALLBACK;
  174.                                 dataarray.push_back(testSpeedData((char*)splitvec[COM_IP].c_str(), (char*)splitvec[COM_LOCATION].c_str()));
  175.                                 m_list->InsertItem(&item);
  176.                                 toadd.push_back(make_pair(splitvec[COM_IP], splitvec[COM_LOCATION]));
  177.                         }
  178.                 }
  179.                 file.close();
  180.                 ProgressThread("正在添加",doadddata,&toadd);
  181.         }
  182. }

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

  200. char toformat[256];

  201. void CFasterDNSDlg::OnLvnGetdispinfoIplist(NMHDR *pNMHDR, LRESULT *pResult)
  202. {//刷新数据
  203.         NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
  204.         // TODO:  在此添加控件通知处理程序代码
  205.         int index = pDispInfo->item.iItem;
  206.         if (dataarray.size() == 0 || index > dataarray.size() - 1)
  207.                 return;
  208.         testSpeedData& cur = dataarray[index];
  209.         switch (pDispInfo->item.iSubItem)
  210.         {
  211.         case COL_IP:
  212.                 pDispInfo->item.pszText = (char*)cur.ip.c_str();
  213.                 break;
  214.         case COL_LOC:
  215.                 pDispInfo->item.pszText = (char*)cur.location.c_str();
  216.                 break;
  217.         case COL_RES:
  218.                 if (cur.responsetime == 0)
  219.                         pDispInfo->item.pszText = "未测速";
  220.                 else if (cur.testtime == cur.failtime)
  221.                         pDispInfo->item.pszText = "测速失败";
  222.                 else
  223.                 {
  224.                         sprintf_s(toformat, "%d ms", cur.responsetime / (cur.testtime - cur.failtime));
  225.                         pDispInfo->item.pszText = toformat;
  226.                 }
  227.                 break;
  228.         case COL_FAIL:
  229.                 if (dataarray[index].testtime == 0)
  230.                         pDispInfo->item.pszText = "未测速";
  231.                 else
  232.                 {
  233.                         sprintf_s(toformat, "%d/%d", cur.failtime, cur.testtime);
  234.                         pDispInfo->item.pszText = toformat;
  235.                 }
  236.                 break;
  237.         }
  238.         *pResult = 0;
  239. }

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

  244. void CFasterDNSDlg::OnSetdns()
  245. {//显示网卡窗口
  246.         std::vector<std::string> selip;
  247.         int uSelectedCount = m_list->GetSelectedCount();
  248.         int nItem = -1;
  249.         if (uSelectedCount > 0)
  250.         {
  251.                 for (int i = 0; i < uSelectedCount; i++)
  252.                 {
  253.                         nItem = m_list->GetNextItem(nItem, LVNI_SELECTED);
  254.                         selip.push_back(dataarray[nItem].ip);
  255.                 }
  256.                 boost::thread(boost::bind(&CFasterDNSDlg::DoDNSConnection, this));
  257.         }

  258.         CSetDnsDlg setdns(selip);
  259.         setdns.DoModal();
  260. }

  261. bool CompareIP(testSpeedData& lParam1, testSpeedData& lParam2)
  262. {
  263.         using namespace boost::asio;
  264.         ip::address& addr1 = ip::address::from_string(lParam1.ip);
  265.         ip::address& addr2 = ip::address::from_string(lParam2.ip);
  266.         if (addr1.is_v4())
  267.         {
  268.                 if (addr2.is_v4())
  269.                 {
  270.                         return addr1.to_v4().to_ulong() < addr2.to_v4().to_ulong();
  271.                 }
  272.                 else
  273.                         return true;
  274.         }
  275.         else
  276.         {
  277.                 return false;
  278.         }
  279. }

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

  284. bool CompareRES(testSpeedData& lParam1, testSpeedData& lParam2)
  285. {
  286.         if (lParam1.failtime || lParam1.lefttime)
  287.                 return true;
  288.         else if (lParam2.failtime || lParam2.lefttime)
  289.                 return false;
  290.         else if (!lParam1.testtime || !lParam2.testtime)
  291.                 return lParam1.testtime < lParam2.testtime;
  292.         else
  293.                 return lParam1.responsetime / lParam1.testtime < lParam2.responsetime / lParam2.testtime;
  294. }

  295. void CFasterDNSDlg::DoSort(bool(*f)(testSpeedData&, testSpeedData&))
  296. {
  297.         if (issorting)
  298.         {
  299.                 AfxMessageBox("排序尚未完成!");
  300.                 return;
  301.         }

  302.         boost::mutex::scoped_lock mdata(datamutex);
  303.         SetDlgItemText(IDC_STATU, "正在排序");
  304.         issorting = true;
  305.         std::sort(dataarray.begin(), dataarray.end(), f);
  306.         for (int i = 0; i < dataarray.size(); i++)
  307.         {
  308.                 LVITEM item = { 0 };
  309.                 item.mask = LVIF_TEXT;
  310.                 item.iItem = i;
  311.                 item.pszText = LPSTR_TEXTCALLBACK;
  312.                 m_list->SendMessage(LVM_SETITEMTEXT, i, (LPARAM)&item);
  313.         }
  314.         SetDlgItemText(IDC_STATU, "排序完毕");
  315.         issorting = false;
  316. }

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

  320.         switch (phdr->iItem)
  321.         {//不要直接修改listview,而是先修改和listview绑定的data,再通知listview
  322.                 case COL_IP:
  323.                         boost::thread(boost::bind(&CFasterDNSDlg::DoSort, this, CompareIP));
  324.                         break;
  325.                 case COL_LOC:
  326.                         boost::thread(boost::bind(&CFasterDNSDlg::DoSort, this, CompareLOC));
  327.                         break;
  328.                 case COL_RES:
  329.                         boost::thread(boost::bind(&CFasterDNSDlg::DoSort, this, CompareRES));
  330.                         break;
  331.                 case COL_FAIL:
  332.                         break;
  333.         }
  334.         *pResult = 0;
  335. }

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

  347. void CFasterDNSDlg::OnDeldns()
  348. {//删除dns,先从数据库中删,再重新加载数据
  349.         int uSelectedCount = m_list->GetSelectedCount();
  350.         int nItem = -1;
  351.         if (uSelectedCount > 0)
  352.         {
  353.                 boost::mutex::scoped_lock mdata(datamutex);
  354.                 std::vector<std::string> temp;
  355.                 for (int i = 0; i < uSelectedCount; i++)
  356.                 {
  357.                         nItem = m_list->GetNextItem(nItem, LVNI_SELECTED);
  358.                         temp.push_back(dataarray[nItem].ip);
  359.                 }
  360.                 dodeldata(&temp, m_list->m_hWnd);
  361.                 dataarray.clear();
  362.                 m_list->DeleteAllItems();
  363.                 boost::thread(boost::bind(getdata, &dataarray, m_list->m_hWnd, GetDlgItem(IDC_STATU)->m_hWnd, &datamutex));
  364.         }
  365. }

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

  368. void testFunc(int index, std::vector<testSpeedData>* rawdata, HWND listview)
  369. {
  370.         testSpeedData& curdata = (*rawdata).at(index);
  371.         std::vector<uint8_t> bufferdata;
  372.         bool got = false;
  373.         while (curdata.lefttime)
  374.         {
  375.                 makedns(bufferdata, domain);
  376.                 int originlen = bufferdata.size();//发送包大小,用于定位返回answer
  377.                 replaceXid(bufferdata, rand() & 0xFFFF);
  378.                 uint32_t usedtime = curdata.timeout;
  379.                 if (!dodnsconnect(curdata.ip, usedtime, bufferdata))
  380.                         curdata.failtime++;
  381.                 else
  382.                 {
  383.                         curdata.responsetime += usedtime;
  384.                         if (!got)
  385.                         {//解析返回包
  386.                                 resolveAnswer(bufferdata, resolvedip, originlen);
  387.                                 got = true;
  388.                         }
  389.                 }       
  390.                 curdata.lefttime--;
  391.         }
  392.         //刷新listview
  393.         LVITEM item = { 0 };
  394.         item.mask = LVIF_TEXT;
  395.         item.iItem = index;
  396.         item.pszText = LPSTR_TEXTCALLBACK;
  397.         SendMessage(listview, LVM_SETITEMTEXT, index, (LPARAM)&item);
  398. }

  399. void CFasterDNSDlg::OnTimer(UINT_PTR nIDEvent)
  400. {
  401.         char status[256];
  402.         sprintf_s(status,"%06d/%06d/%06d", task.size(), maxtask, dataarray.size());
  403.         SetDlgItemText(IDC_TESTPROG, status);
  404.         CDialogEx::OnTimer(nIDEvent);
  405. }

  406. void CFasterDNSDlg::DoDNSConnection()
  407. {//设置testSpeedData
  408.         maxtask = task.size();
  409.         CString domaina;
  410.         GetDlgItemText(IDC_DOMAIN, domaina);
  411.         ::domain = (LPCTSTR)domaina;
  412.         resolvedip.clear();
  413.         ThreadPool<testSpeedData> newtaskset(taskmutex);
  414.         newtaskset.Attach(threadnum, &task, &dataarray,m_list->m_hWnd);
  415.         newtaskset.Exec(testFunc);
  416.         OnBnClickedViewip();
  417. }

  418. void CFasterDNSDlg::InitOne(testSpeedData& obj)
  419. {//初始化单个数据
  420.         obj.failtime = 0;
  421.         obj.lefttime = repeattime;
  422.         obj.responsetime = 0;
  423.         obj.testtime = repeattime;
  424.         obj.timeout = timeout;
  425. }

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

  443. void CFasterDNSDlg::OnBnClickedStart()
  444. {//测试选中
  445.         boost::mutex::scoped_lock mtask(taskmutex);
  446.         if (!task.empty())
  447.         {
  448.                 AfxMessageBox("测试尚未结束,请先停止测试");
  449.                 return;
  450.         }
  451.         int uSelectedCount = m_list->GetSelectedCount();
  452.         int nItem = -1;
  453.         if (uSelectedCount > 0)
  454.         {
  455.                 task.clear();
  456.                 for (int i = 0; i < uSelectedCount; i++)
  457.                 {
  458.                         nItem = m_list->GetNextItem(nItem, LVNI_SELECTED);
  459.                         InitOne(dataarray[nItem]);
  460.                         task.push_back(nItem);
  461.                 }
  462.                 boost::thread(boost::bind(&CFasterDNSDlg::DoDNSConnection, this));
  463.         }
  464. }

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

  472. void CFasterDNSDlg::OnBnClickedViewip()
  473. {
  474.         CShowIp ipdlg(domain, resolvedip);
  475.         ipdlg.DoModal();
  476. }

  477. void CFasterDNSDlg::OnAdddns()
  478. {
  479.         OnBnClickedAddDNS();
  480. }

  481. void CFasterDNSDlg::OnModify()
  482. {
  483.         CGlobalSetting settings(threadnum, timeout, repeattime);
  484.         settings.DoModal();
  485. }

  486. void CFasterDNSDlg::OnStartall()
  487. {
  488.         OnBnClickedAllinone();
  489. }

  490. void CFasterDNSDlg::OnStopall()
  491. {
  492.         OnBnClickedStop();
  493. }

  494. void CFasterDNSDlg::OnTestip()
  495. {
  496.         OnBnClickedViewip();
  497. }

  498. void CFasterDNSDlg::OnExit()
  499. {
  500.         SendMessage(WM_CLOSE, 0, 0);
  501. }

  502. void CFasterDNSDlg::OnAllinone()
  503. {
  504.         OnBnClickedAllinone();
  505. }

  506. void CFasterDNSDlg::OnStart()
  507. {
  508.         OnBnClickedStart();
  509. }

  510. void CFasterDNSDlg::OnStop()
  511. {
  512.         OnBnClickedStop();
  513. }
复制代码


functions.cpp
  1. #include "stdafx.h"

  2. #include <boost/function.hpp>
  3. #include <boost/asio.hpp>
  4. #include <boost/thread.hpp>
  5. #include <boost/bind.hpp>
  6. #include <boost/date_time.hpp>
  7. #include <boost/algorithm/string.hpp>
  8. #include <boost/lexical_cast.hpp>
  9. #include <boost/format.hpp>
  10. #include <boost/system/error_code.hpp>
  11. #include <vector>
  12. #include <set>
  13. #include <winsock.h>
  14. #include <stdint.h>
  15. #include <iphlpapi.h>
  16. #include <windows.h>
  17. #include "functions.h"
  18. #include "sqlite3.h"
  19. #pragma comment(lib,"sqlite3.lib")
  20. #pragma comment(lib,"iphlpapi.lib")
  21. /************************************************************************/
  22. /* 单例模式获取实例                                                     */
  23. /************************************************************************/
  24. std::vector<testSpeedData>* ipcontainer::testdata = NULL;
  25. int* ipcontainer::pcount = NULL;
  26. HWND ipcontainer::pwnd = NULL;

  27. ipcontainer& ipcontainer::getInstance()
  28. {
  29.         boost::mutex mio;
  30.         boost::mutex::scoped_lock lock(mio);
  31.         static ipcontainer container;
  32.         return container;
  33. }

  34. /************************************************************************/
  35. /* 向数据库中增加dns数据
  36.         ip:待添加dns服务器ip地址(非域名)        addr:待添加dns服务器地理位置        */
  37. /************************************************************************/
  38. bool ipcontainer::adddata(const std::string& ip, const std::string& addr)
  39. {
  40.         int status = SQLITE_OK;
  41.         char* zErrMsg = NULL;
  42.         std::string toadd = "insert into dnss values ('" + ip + "','" + addr + "')";
  43.         try
  44.         {
  45.                 status = sqlite3_exec(db, toadd.c_str(), NULL, NULL, &zErrMsg);
  46.                 if (status != SQLITE_OK)
  47.                         throw "Add failed!";
  48.         }
  49.         catch (...)
  50.         {
  51.                 return false;
  52.         }
  53.         return true;
  54. }

  55. /************************************************************************/
  56. /* 从数据库中删除dns数据
  57.         ip:待删除dns服务器ip地址(非域名)                                                                        */
  58. /************************************************************************/
  59. bool ipcontainer::deldata(const std::string& ip)
  60. {
  61.         int status = SQLITE_OK;
  62.         char* zErrMsg = NULL;
  63.         std::string toadd = "delete from dnss where ipaddr = '" + ip + "'";
  64.         try
  65.         {
  66.                 status = sqlite3_exec(db, toadd.c_str(), NULL, NULL, &zErrMsg);
  67.                 if (status != SQLITE_OK)
  68.                         throw "Del failed!";
  69.         }
  70.         catch (...)
  71.         {
  72.                 return false;
  73.         }
  74.         return true;
  75. }

  76. /************************************************************************/
  77. /* 获取dns数据总入口
  78.         dataparam:存放获得数据结果                                                                                        */
  79. /************************************************************************/
  80. bool ipcontainer::getdata(std::vector<testSpeedData>* dataparam, HWND listctrl)
  81. {
  82.         try
  83.         {
  84.                 ipcontainer::testdata = dataparam;
  85.                 ipcontainer::pwnd = listctrl;
  86.                 int status = SQLITE_OK;
  87.                 char* zErrMsg = NULL;
  88.                 status = sqlite3_exec(db, "select * from dnss", getdatacallback, NULL, &zErrMsg);
  89.                 if (status != SQLITE_OK)
  90.                         throw "Get failed!";
  91.         }
  92.         catch (...)
  93.         {
  94.                 ipcontainer::testdata = NULL;
  95.                 ipcontainer::pwnd = NULL;
  96.                 return false;
  97.         }
  98.         ipcontainer::testdata = NULL;
  99.         ipcontainer::pwnd = NULL;
  100.         return true;
  101. }

  102. /************************************************************************/
  103. /* 获取dns数据记录总数                                                                    */
  104. /************************************************************************/
  105. bool ipcontainer::getcount(int& count)
  106. {
  107.         try
  108.         {
  109.                 ipcontainer::pcount = &count;
  110.                 int status = SQLITE_OK;
  111.                 char* zErrMsg = NULL;
  112.                 status = sqlite3_exec(db, "select count(*) from dnss", getcountcallback, NULL, &zErrMsg);
  113.                 if (status != SQLITE_OK)
  114.                         throw "Get failed!";
  115.         }
  116.         catch (...)
  117.         {
  118.                 ipcontainer::pcount = NULL;
  119.                 return false;
  120.         }
  121.         ipcontainer::pcount = NULL;
  122.         return true;
  123. }

  124. /************************************************************************/
  125. /* 析构时关闭数据库                                                     */
  126. /************************************************************************/
  127. ipcontainer::~ipcontainer()
  128. {
  129.         ipcontainer::testdata = NULL;
  130.         ipcontainer::pcount = NULL;
  131.         ipcontainer::pwnd = NULL;
  132.         sqlite3_close(db);
  133.         db = NULL;
  134. }

  135. /************************************************************************/
  136. /* 构造函数打开数据库                                                                                                        */
  137. /************************************************************************/
  138. ipcontainer::ipcontainer()
  139. {
  140.         int status = SQLITE_OK;
  141.         db = NULL;
  142.         status = sqlite3_open(DATABASE, &db);
  143.         if (status != SQLITE_OK)
  144.                 throw "Open failed!";
  145. }

  146. /************************************************************************/
  147. /* 获取记录数据数组的回调函数,用于获取记录数据数组
  148.         argc:获得条目个数=2                argv[0]:ip                        argv:location                        */
  149. /************************************************************************/
  150. int ipcontainer::getdatacallback(void *NotUsed, int argc, char **argv, char **azColName)
  151. {
  152.         LVITEM item = { 0 };
  153.         item.mask = LVIF_TEXT;
  154.         item.iItem = ipcontainer::testdata->size();
  155.         item.lParam = item.iItem;
  156.         item.pszText = LPSTR_TEXTCALLBACK;
  157.         ipcontainer::testdata->push_back(testSpeedData(argv[0], argv[1]));
  158.         SendMessage(pwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
  159.         return 0;
  160. }

  161. /************************************************************************/
  162. /* 获取记录条目的回调函数,用于得到记录条目   
  163.         argc:获得条目个数=1                argv[0]:记录条目                                                        */
  164. /************************************************************************/
  165. int ipcontainer::getcountcallback(void *NotUsed, int argc, char **argv, char **azColName)
  166. {
  167.         try
  168.         {
  169.                 *ipcontainer::pcount = boost::lexical_cast<int>(argv[0]);
  170.         }
  171.         catch (...)
  172.         {
  173.                 *ipcontainer::pcount = 0;
  174.         }
  175.         return 0;
  176. }

  177. /************************************************************************/
  178. /* 增加dns数据总入口
  179. setpos:设置进度显示回调函数                dataparam:要添加的数据阵列*/
  180. /************************************************************************/
  181. bool doadddata(dbData* dataparam, HWND progctrl)
  182. {
  183.         int size = dataparam->size() / 100;
  184.         int i = 0, j = 0;
  185.         SendMessage(progctrl, PBM_SETPOS, 0, 0);
  186.         try
  187.         {
  188.                 dbData::const_iterator itor = dataparam->begin();
  189.                 ipcontainer& container=ipcontainer::getInstance();
  190.                 while (itor != dataparam->end())
  191.                 {
  192.                         container.adddata(itor->first, itor->second);
  193.                         ++itor;
  194.                         ++i;
  195.                         if (i >= size)
  196.                         {
  197.                                 i = 0;
  198.                                 SendMessage(progctrl, PBM_SETPOS, ++j, 0);
  199.                         }
  200.                 }
  201.         }
  202.         catch (...)
  203.         {
  204.                 //发生错误
  205.                 return false;
  206.         }
  207.         return true;
  208. }

  209. /************************************************************************/
  210. /* 删除dns数据总入口
  211. setpos:设置进度显示回调函数                dataparam:要删除的数据阵列*/
  212. /************************************************************************/
  213. bool dodeldata(std::vector<std::string>* dataparam, HWND progctrl)
  214. {
  215.         int size = dataparam->size() / 100;
  216.         int i = 0, j = 0;
  217.         SendMessage(progctrl, PBM_SETPOS, 0, 0);
  218.         try
  219.         {
  220.                 std::vector<std::string>::iterator itor = dataparam->begin();
  221.                 ipcontainer& container = ipcontainer::getInstance();
  222.                 while (itor != dataparam->end())
  223.                 {
  224.                         container.deldata(*itor);
  225.                         ++itor;
  226.                         ++i;
  227.                         if (i >= size)
  228.                         {
  229.                                 i = 0;
  230.                                 SendMessage(progctrl, PBM_SETPOS, ++j, 0);
  231.                         }
  232.                 }
  233.         }
  234.         catch (...)
  235.         {
  236.                 //发生错误
  237.                 return false;
  238.         }
  239.         return true;
  240. }

  241. /************************************************************************/
  242. /* 尝试http连接
  243.         ip:要测试连通性的地址                timeout:超时返回                                                */
  244. /************************************************************************/
  245. bool dohttpconnect(const std::string& ip,uint32_t& timeout)
  246. {//ip不能是域名 timeout同时用于设置超时和计时
  247.         using namespace boost::asio;
  248.         using namespace boost::posix_time;
  249.         try
  250.         {
  251.                 tcpclient c;
  252.                 boost::system::error_code ec;
  253.                 setsockopt(c.socket_.native(), SOL_SOCKET, SO_RCVTIMEO, (const char*)timeout, sizeof(timeout));
  254.                 ip::tcp::endpoint ep(ip::address::from_string(ip), PORT_HTTP);
  255.                 ptime ptStart = microsec_clock::local_time();
  256.                 c.connect(ep, boost::posix_time::millisec(timeout), ec);
  257.                 if (ec.value())
  258.                         throw "error";
  259.                 ptime ptEnd = microsec_clock::local_time();
  260.                 timeout = (int32_t)(ptEnd - ptStart).total_milliseconds();
  261.         }
  262.         catch (...)
  263.         {
  264.                 return false;
  265.         }
  266.         return true;
  267. }

  268. /************************************************************************/
  269. /* 尝试dns连接
  270.         ip:要测试连通性的地址                timeout:超时返回               
  271.         bufferdata:用于发送和接收数据                                                                                */
  272. /************************************************************************/
  273. bool dodnsconnect(const std::string& ip, uint32_t& timeout,std::vector<uint8_t>& bufferdata)
  274. {//bufferdata用于输入和输出 ip为服务器地址
  275.         using namespace boost::asio;
  276.         using namespace boost::posix_time;
  277.         try
  278.         {
  279.                 udpclient c(ip::udp::endpoint(ip::udp::v4(), rand() & 0x7FFF + 0x8000));
  280.                 boost::system::error_code ec;
  281.                 setsockopt(c.socket_.native(), SOL_SOCKET, SO_RCVTIMEO, (const char*)timeout, sizeof(timeout));
  282.                 setsockopt(c.socket_.native(), SOL_SOCKET, SO_BROADCAST, "\0\0\0\0", 4);
  283.                 ip::udp::endpoint ep(ip::address::from_string(ip), PORT_DNS);
  284.                 c.socket_.send_to(buffer((bufferdata)),ep);
  285.                 bufferdata.clear();
  286.                 bufferdata.resize(MAXS_RECVNUM);
  287.                 ptime ptStart = microsec_clock::local_time();
  288.                 c.receive(buffer(bufferdata), boost::posix_time::millisec(timeout), ec);
  289.                 if (ec.value())
  290.                         throw "error";
  291.                 ptime ptEnd = microsec_clock::local_time();
  292.                 timeout = (int32_t)(ptEnd - ptStart).total_milliseconds();
  293.         }
  294.         catch (...)
  295.         {
  296.                 return false;
  297.         }
  298.         return true;
  299. }

  300. /************************************************************************/
  301. /* 构造dns数据包
  302.         bufferdata:用于存储构造数据包结果
  303.         testdomain:用于验证的域名,不能用ip地址                                                                */
  304. /************************************************************************/
  305. void makedns(std::vector<uint8_t>& bufferdata, const std::string& testdomain)
  306. {//testip为验证ip,此函数用于testip更换时;Xid更换时用replaceXid
  307.         bufferdata.resize(sizeof(DNS_HEADER));
  308.         DNS_HEADER* pheader = (DNS_HEADER*)bufferdata.data();
  309.         memset(pheader, 0, sizeof(DNS_HEADER));
  310.         pheader->RecursionDesired = 1;
  311.         pheader->QuestionCount = 1;//查询一个域名
  312.         DNS_BYTE_FLIP_HEADER_COUNTS(pheader);
  313.         boost::asio::ip::address addr;
  314.         spliter splitvec;
  315.         boost::split(splitvec, testdomain, boost::is_any_of("."));
  316.         for (spliter::iterator itor = splitvec.begin(); itor != splitvec.end(); ++itor)
  317.         {
  318.                 bufferdata.push_back((*itor).length());
  319.                 bufferdata.insert(bufferdata.end(), (*itor).begin(),(*itor).end());
  320.         }
  321.         uint8_t tailer[SIZE_DNSTAILER] = { 0x00, 0x00, 0x01, 0x00, 0x01 };
  322.         bufferdata.insert(bufferdata.end(), tailer, tailer+SIZE_DNSTAILER);
  323. }

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

  332. /************************************************************************/
  333. /*从返回包结果中解析获取到的地址   
  334.         bufferdata:服务器返回的待解析数据        resolveip:存储结果
  335.         originlen:发送包大小*/
  336. /************************************************************************/
  337. void resolveAnswer(std::vector<uint8_t>& bufferdata, std::set<std::string>& resolvedip, int originlen)
  338. {
  339.         DNS_HEADER* pheader = (DNS_HEADER*)bufferdata.data();
  340.         DNS_BYTE_FLIP_HEADER_COUNTS(pheader);
  341.         uint8_t* ptr = (uint8_t*)pheader + originlen;
  342.         for (int i = 0; i < pheader->AnswerCount; i++)
  343.         {
  344.                 DNSANSWER_HEADER* aheader = (DNSANSWER_HEADER*)ptr;
  345.                 DNS_BYTE_FLIP_ANSWERHEADER_COUNTS(aheader);
  346.                 if(aheader->Type == 1)//A:host address
  347.                 {
  348.                         BYTE* cdata = (BYTE*)aheader + sizeof(DNSANSWER_HEADER);
  349.                         if (aheader->Datalength == 4)//ipv4
  350.                         {
  351.                                 char temp[16];
  352.                                 sprintf_s(temp, "%d.%d.%d.%d", cdata[0], cdata[1], cdata[2], cdata[3]);
  353.                                 resolvedip.insert(std::string(temp));
  354.                         }
  355.                         else if (aheader->Datalength == 6)//ipv6
  356.                         {
  357.                                 //v6的没有条件研究呢。。。
  358.                         }
  359.                 }
  360.                 ptr += aheader->Datalength + sizeof(DNSANSWER_HEADER);
  361.         }
  362. }

  363. /************************************************************************/
  364. /* 获取网卡适配器
  365.         interfaces:存储结果                                                                                                        */
  366. /************************************************************************/
  367. bool getinterface(std::vector<std::string>& interfaces)
  368. {
  369.         DWORD dwRetVal = 0;
  370.         ULONG outBufLen = 15000;
  371.         LPVOID lpMsgBuf = NULL;
  372.         PIP_ADAPTER_ADDRESSES pAddress = NULL;
  373.         interfaces.clear();
  374.         do
  375.         {
  376.                 pAddress = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, outBufLen);
  377.                 if (pAddress == NULL)
  378.                         return false;
  379.                 dwRetVal = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddress, &outBufLen);
  380.                 if (dwRetVal == ERROR_BUFFER_OVERFLOW)
  381.                 {
  382.                         HeapFree(GetProcessHeap(), 0, pAddress);
  383.                         pAddress = NULL;
  384.                 }
  385.         } while (dwRetVal == ERROR_BUFFER_OVERFLOW);
  386.         if (dwRetVal != NO_ERROR)
  387.                 return false;

  388.         PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddress;
  389.         while (pCurrAddresses)
  390.         {
  391.                 HKEY hkResult;
  392.                 std::string query = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\";
  393.                 query += pCurrAddresses->AdapterName;
  394.                 query += "\\Connection\";
  395.                 dwRetVal = RegOpenKey(HKEY_LOCAL_MACHINE, query.c_str(), &hkResult);
  396.                 if (dwRetVal == ERROR_SUCCESS)
  397.                 {
  398.                         char buffer[256];
  399.                         LONG cbData = 256;
  400.                         dwRetVal = RegQueryValue(hkResult, "Name", buffer, &cbData);
  401.                         if (dwRetVal == ERROR_SUCCESS)
  402.                         {
  403.                                 interfaces.push_back((char*)buffer);
  404.                         }
  405.                 }
  406.                 pCurrAddresses = pCurrAddresses->Next;
  407.         }

  408.         if (pAddress)
  409.                 HeapFree(GetProcessHeap(), 0, pAddress);
  410.         return true;
  411. }

  412. /************************************************************************/
  413. /* 设置指定网卡适配器dns
  414.         setpos:设置进度显示回调函数                interfaces:待设置适配器               
  415.         address为点分十进制地址                                                                                                */
  416. /************************************************************************/
  417. bool setinterface(std::vector<std::string>& interfaces, std::vector<std::string>& addresss, HWND progctrl)
  418. {
  419.         using namespace boost::asio;
  420.         STARTUPINFO StartupInfo = { 0 };
  421.         PROCESS_INFORMATION ProcessInfo = { 0 };
  422.         StartupInfo.cb = sizeof(STARTUPINFO);
  423.         StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  424.         StartupInfo.wShowWindow = SW_HIDE;
  425.         std::string cmd;
  426.         int count = 0;
  427.         SendMessage(progctrl, PBM_SETPOS, 0, 0);
  428.         for (std::vector<std::string>::iterator itori = interfaces.begin(); itori != interfaces.end(); ++itori)
  429.         {
  430.                 BOOL bRet;
  431.                 cmd = "netsh interface ipv4 set dns name="" + *itori + "" source=static addr=none";
  432.                 //清除DNS设置       
  433.                 bRet=CreateProcess(NULL, (char*)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
  434.                 if (!bRet)
  435.                         return false;
  436.                 if (ProcessInfo.hProcess)
  437.                         WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
  438.                 cmd = "netsh interface ipv6 set dns name="" + *itori + "" source=static addr=none";
  439.                 bRet = CreateProcess(NULL, (char*)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
  440.                 if (!bRet)
  441.                         return false;
  442.                 if (ProcessInfo.hProcess)
  443.                         WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
  444.                 SendMessage(progctrl, PBM_SETPOS, int(100 * (float)count++ / interfaces.size()), 0);
  445.                 SetWindowText(progctrl, ("正在清除设置 " + *itori).c_str());
  446.                 for (std::vector<std::string>::iterator itora = addresss.begin(); itora != interfaces.end(); ++itora)
  447.                 {
  448.                         if ((ip::address::from_string(*itora)).is_v4())
  449.                                 cmd = "netsh interface ipv4 add dns name="" + *itori + "" addr=" + *itora;
  450.                         else
  451.                                 cmd = "netsh interface ipv6 add dns name="" + *itori + "" addr=" + *itora;
  452.                         SetWindowText(progctrl, ("正在设置 " + *itora).c_str());
  453.                         bRet = CreateProcess(NULL, (char*)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);
  454.                         if (!bRet)
  455.                                 return false;
  456.                         if (ProcessInfo.hProcess)
  457.                                 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
  458.                 }
  459.         }
  460.         return true;
  461. }

  462. /************************************************************************/
  463. /* 封装getcount                                                         */
  464. /************************************************************************/
  465. bool getcount(int& count)
  466. {
  467.         try
  468.         {
  469.                 ipcontainer::getInstance().getcount(count);
  470.         }
  471.         catch (...)
  472.         {
  473.                 return false;
  474.         }
  475.         return true;
  476. }

  477. /************************************************************************/
  478. /* 封装getdata                                                          */
  479. /************************************************************************/
  480. bool getdata(std::vector<testSpeedData>* dataparam, HWND listctrl, HWND statu, boost::mutex* mu)
  481. {
  482.         boost::mutex::scoped_lock mdata(*mu);
  483.         SetWindowText(statu, "正在初始化数据!");
  484.         try
  485.         {
  486.                 ipcontainer::getInstance().getdata(dataparam, listctrl);
  487.         }
  488.         catch (...)
  489.         {
  490.                 return false;
  491.         }
  492.         SetWindowText(statu, "初始化完毕!");
  493.         return true;
  494. }
复制代码

回复

使用道具 举报

 楼主| 发表于 2015-3-9 09:30:37 | 显示全部楼层
完整工程:http://pan.baidu.com/s/1dDrjRDB
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-22 02:40 , Processed in 0.042312 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表