导语:
项目名称:基于Qt开发的网络诊断工具
开发环境:VS2008
QT版本:4.7
数据读入:用户自行选中的.ini配置文件
功能实现:解析.ini文件,实时检测相关的域名连通性以及DNS解析的结果是否匹配.ini文件对应内容
模块设计:
WorkThread //工作线程类
Log //日志打印类
Mainwindow //主窗口类
Mainwindow2//弹窗类
项目源码:
- WorkThread.hpp
//WorkThread.h
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
#include <QMap>
#include <QString>
#include <QTcpSocket>
#include<QHostInfo>
#include <windows.h>
#include <QProgressDialog>
#include <QDebug>
#include <QHostAddress>
#include <QtNetwork\qhostinfo.h>
#include <QTcpSocket>
#include <QMessageBox>
#include<QMutex>
#include <time.h>
#include <QAbstractSocket>
#include <QTimer>
#include<QProgressDialog>
#include "LOG.h"
//#include "Log.hpp"
class WorkerThread : public QThread{
Q_OBJECT
signals:
void windowShow(QString text);
private:
QVector<QString>_v1; //元素是每一段
QVector<QString>_v2; //元素是每一小段每一行内容
QVector<QString>_domain; //存储每一段的域名部分
QMap< QString,QVector<QString> >_m;
QString _text;
QProgressDialog* progress;
int count;
LOG* log;
//QTimer *timer;
QMutex mutex;
private slots:
void lookedUp(const QHostInfo &host);
public:
bool Search(QString s1,QString s2);
WorkerThread(QObject *parent=0);
~WorkerThread();
void RequsetNewthread(QVector<QString> v,QMap< QString,QVector<QString> >m);
protected:
void run();
};
#endif // WORKTHREAD_H
//WorkThread.cpp
#include "workthread.h"
WorkerThread::WorkerThread(QObject *parent)
: QThread(parent)
{
_text+="\n******************************************************************\n\n";
_text+="\n******************** NetWork Checking... ... *******************\n\n";
_text+="\n******************************************************************\n\n";
count=0;
log=new LOG();
}
void WorkerThread::RequsetNewthread(QVector<QString> v, QMap< QString,QVector<QString> >m){
_v1=v;
_m=m;
start();
}
void WorkerThread::run(){
/* timer = new QTimer(this);
timer->start(100);
*/
progress=new QProgressDialog("Parsing content", "Cancel", 0,100);
progress->setWindowModality(Qt::WindowModal);
progress->setMinimumDuration(5);
progress->setWindowTitle("Parsing now ...");
progress->show();
//为什么点击cancel之后不报警告
if(progress->wasCanceled())
{
QMessageBox::warning(NULL,"Warning","you have canceled this action.");
return;
}
for (int i = 0; i < 100; i++) {
Sleep(100);
progress->setValue(i);
}
progress->setValue(100);
while(1){//实时监控
Sleep(1000);
_domain.clear();
count=0;
QString log_=log->Log_record(" Paring result: ");
_text+=log_;
_text+="\n";
//对每一个小段进行处理
for( int i=0;i<9;++i){
QString arr(_v1[i]);
_v2.clear();
//以\n为分隔符去提取,将每一段的没一行的内容作为一个vecor的元素 [account.wps.cn]\ndirectUseHttpDns=0\nip1=140.210.77.190\nip2=114.112.36.130\nip6=114.112.66.245
size_t begin=0;
do
{
size_t end=arr.indexOf("\n",begin);
if(end==-1) {
//最后一次,应该把从begin下标开始全部都读进去
QString replenish=arr.mid(begin);
_v2.push_back(replenish);
break;
}
QString tmp_var=arr.mid(begin,end-begin);
_v2.push_back(tmp_var);
begin=end+1;
} while(1);
//判断v2[0]元素即指定域名的连通性
QTcpSocket socket(0);
socket.abort(); //取消原有连接
socket.connectToHost(_v2[0],80); //建立一个TCP连接 第二个参数是服务器方面的端口号
// socket->connectToHost("imap", 143);
if(socket.waitForConnected(1000))
{
_text+=(_v2[0]+" is regular... \n\n");
}
else{
_text+=(_v2[0]+" is not regular... \n\n");
}
_domain.push_back(_v2[0]);
}//end of for...
emit windowShow(_text);
//把每一个域名都存储一下
for(int j=0;j<9;++j){
QHostInfo::lookupHost(_domain[j], this, SLOT(lookedUp(QHostInfo)));
}
}//end of while(1);
}
void WorkerThread::lookedUp(const QHostInfo &host)
{
mutex.lock();
++count;
QString tag;
_text+="\n";
_text+=(host.hostName()+" analytical result is : ");
QList<QHostAddress> addrList = host.addresses();
if (!addrList.isEmpty())
{
for (int i = 0; i < addrList.size(); i++)
{
_text+=(addrList[i].toString());
if(Search(addrList[i].toString(),host.hostName())) { //Search():与host关联的域名在v2的元素项中一一比对判断是否存在
tag="true";
_text+=(" "+tag+"\n");
}
else{
tag="false";
_text+=(" "+tag+"\n");
}
}//end of for:对应解析出的相关的ip列表遍历的循环
}
//如果列表为空,打印LOG
else{
_text+="The analytical result is NULL...";
}
if(count==9){
_text += "\n\n\n\n\n\n";
emit windowShow(_text);
}
mutex.unlock();
}
bool WorkerThread::Search(QString s1,QString s2){
//在 成员变量 m map<string,vector<string>>中去查找
QVector<QString>vv=_m[s2];
for(int i=0;i<vv.size();++i){
QString edit=vv[i].mid(4);
if( QString::compare(s1, edit) == 0){ //QString 的字符串相等的比对方法
return true;
}
}
return false;
}
WorkerThread::~WorkerThread(){
delete progress;
delete log;
//delete timer;
}
//完善的话: 1.可以在弹窗之前增加一个解析的界面设计:进度条对话框 2.每一个大段前打印一次Log 3.窗口伴随下移
- Log.hpp
//Log.h
#ifndef LOG_H
#define LOG_H
#include <QString>
#include <windows.h>
class LOG{
public:
QString GetTimeStamp();
QString Log_record(QString message_);
};
#endif
//Log.cpp
#include "LOG.h"
QString LOG::GetTimeStamp(){
QString str_year;
QString str_month;
QString str_day;
QString str_hour;
QString str_minute;
QString str_second;
QString str_msecond;
QString str_dayofweek;
QString time_;
SYSTEMTIME sys;
GetLocalTime( &sys );
str_year = QString::number(sys.wYear);
str_month = QString::number(sys.wMonth);
str_day = QString::number(sys.wDay);
str_hour = QString::number(sys.wHour);
str_minute = QString::number(sys.wMinute);
str_second = QString::number(sys.wSecond);
str_msecond = QString::number(sys.wMilliseconds);
str_dayofweek = QString::number(sys.wDayOfWeek);
time_+=(str_year+"."+str_month+"."+str_day+" "+" "+str_hour+"h"+ " : "+str_minute+"min"+" : "+str_second+"s "+" : "+str_msecond+"ms "+"DayOfWeek: " +str_dayofweek );
return time_;
}
QString LOG:: Log_record(QString message_)
{
QString StringTime;
QString tmp=GetTimeStamp();
StringTime="["+tmp+"]"+message_;
return StringTime;
}
- test.hpp
//test.h
#ifndef TEST_H
#define TEST_H
#include <QMainWindow>
#include <QTextEdit>
#include <QAction>
#include <QMenuBar>
#include<windows.h>
#include <QWidget>
#include <QDialog>
#include <QMessageBox>
#include<QThread>
#include <QToolBar>
#include <QTime>
#include<fstream>
#include<QDebug>
#include<QPushButton>
#include <QValidator>
#include <QGridLayout>
#include <QFileDialog>
#include<QTextEdit>
#include<QString>
#include <QInputDialog>
#include <QList>
#include "workthread.h"
//弹窗类
class MainWindow2 : public QMainWindow{
Q_OBJECT
public:
MainWindow2(QWidget *parent = 0);
~MainWindow2();
//void Show_window(QString content);
void mfunc_parse(QVector<QString>v,QMap< QString,QVector<QString> >m);
private:
QAction *saveAction;
public:
QTextEdit* textEdit2; //文本框指针
WorkerThread thread_; //线程类对象
private slots:
void save();
void onWindowShow(QString text);
};
//主窗口类
class MainWindow : public QMainWindow{
Q_OBJECT
public:
//void mfunc_parse();
//bool Search(QString s1,QString s2);
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
//void func_parse(QString s,QTextEdit* &textEdit2);
void RequsetNew(QVector<QString> v, QMap<QString,QVector<QString>>m);
private slots:
void open();
void save();
void parse();
protected:
void funcParse();
private:
QAction *saveAction;
QAction *openAction;
QAction *parseAction;
QTextEdit* textEdit;
QString path; //保存打开文件的路径
QString str; //用来传递文本内容
QVector<QString>v1;//元素是每一段
QVector<QString>v2; //元素是每一小段每一行内容
MainWindow2 win2;
QMap< QString,QVector<QString> >m;
//static QString tmp; //用来诊断信息的(+=)输出
};
#endif // MAINWINDOW_H
//test.cpp
#include"test.h"
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent){
setWindowTitle(tr(" opening new Window..."));
textEdit2 = new QTextEdit(this);
setCentralWidget(textEdit2);
saveAction = new QAction(QIcon(":/new_mini/doc-open2"), tr("&Save..."), this);
connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
//添加到菜单栏
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(saveAction);
//添加到工具栏
QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(saveAction);
connect( &thread_, SIGNAL(windowShow(QString )),
this, SLOT(onWindowShow(QString)) );
statusBar();
}
void MainWindow2::save(){
QString path = QFileDialog::getSaveFileName(this,
tr("Open File"),
".",
tr("Text Files(*.txt)"));
if(!path.isEmpty()) {
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, tr("Write File"),
tr("Cannot open file:\n%1").arg(path));
return;
}
QTextStream out(&file);
out << textEdit2->toPlainText();
file.close();
} else {
QMessageBox::warning(this, tr("Path"),
tr("You did not select any file."));
}
}
void MainWindow2:: mfunc_parse(QVector<QString>v, QMap< QString,QVector<QString> >m){
thread_.RequsetNewthread(v,m);
}
//判断玩HOST连通性之后,再去解析拿到关联的ip地址列表,然后去比对
///执行流在这块存在问题: 并没有按照预期执行到这块之后然后去拿到关系的IP列表进行判断
void MainWindow2::onWindowShow(QString text){
textEdit2->setText(text);
this->show();
}
MainWindow2::~MainWindow2(){
delete textEdit2;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////华丽分割//////////////////////////华丽分割////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent){
setWindowTitle(tr("Main Window"));
textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
//win2=new MainWindow2(this);
//设置图标
openAction = new QAction(QIcon(":/new_mini/doc-open1"), tr("&Open..."), this);
parseAction = new QAction(QIcon(":/new_mini/doc-open3"), tr("&Parse..."), this);
saveAction = new QAction(QIcon(":/new_mini/doc-open2"), tr("&Save..."), this);
//设置快捷键
openAction->setShortcuts(QKeySequence::Open);
saveAction->setShortcuts(QKeySequence::Save);
//设置提示信息
openAction->setStatusTip(tr("Open an existing file"));
saveAction->setStatusTip(tr("Save a file"));
parseAction->setStatusTip(tr("Parse an existing file"));
//设置信号槽
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
connect(parseAction, SIGNAL(triggered()), this, SLOT(parse()));
//添加到菜单栏
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
file->addAction(saveAction);
file->addAction(parseAction);
//添加到工具栏
QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);
toolBar->addAction(saveAction);
toolBar->addAction(parseAction);
statusBar();
}
void MainWindow::funcParse(){
//对content字符串S进行预处理,先提取第一段
QString tmp_;//包含每一小段全部内容的string
QVector<QString>vtmp;
//利用循环以'\n\n'为分隔符,把每一段的内容push进v1;
size_t start=0;
size_t index=0;
for(int i=0;i<10-1;++i){
vtmp.clear();
size_t finish=str.indexOf("\n\n",start); //遇到两个换行符的时候然后停止,读取一个段
//if(finish==-1)
// break;
tmp_=str.mid(start,finish-start);
v1.push_back(tmp_);
start=finish+2;
qDebug()<<tmp_;
size_t end=tmp_.indexOf("\n",0);
QString nowords=tmp_.mid(0,end);//tmp_的第一行
size_t begin=0;
do
{
//
size_t end=tmp_.indexOf("\n",begin);
if(end==-1) {
//最后一次,应该把从begin下标开始全部都读进去
QString replenish=tmp_.mid(begin);
vtmp.push_back(replenish);
break;
//
}
QString tmp_var=tmp_.mid(begin,end-begin);
vtmp.push_back(tmp_var);
begin=end+1;
}while(1);
m[nowords]=vtmp;
} // V1每一个大段的内容解析完毕
}
//openAction的槽函数
void MainWindow::open(){
QString path = QFileDialog::getOpenFileName(this,
tr("Open File"),
".",
tr("Text Files(*.txt)"));
if(!path.isEmpty()) {
QFile file(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::warning(this, tr("Read File"),
tr("Cannot open file:\n%1").arg(path));
return;
}
QTextStream in(&file);
str=in.readAll();
textEdit->setText(str);
file.close();
} else {
QMessageBox::warning(this, tr("Path"),
tr("You did not select any file."));
}
//打开之后跟着调用一个函数去填充V1和m的内容
funcParse();
}
//saveAction的槽函数
void MainWindow::save(){
QString path = QFileDialog::getSaveFileName(this,
tr("Open File"),
".",
tr("Text Files(*.txt)"));
if(!path.isEmpty()) {
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, tr("Write File"),
tr("Cannot open file:\n%1").arg(path));
return;
}
QTextStream out(&file);
out << textEdit->toPlainText();
file.close();
} else {
QMessageBox::warning(this, tr("Path"),
tr("You did not select any file."));
}
}
void MainWindow::RequsetNew(QVector<QString> v, QMap<QString,QVector<QString>>m){
win2.mfunc_parse(v,m);
}
//parseAction的槽函数
void MainWindow::parse(){
RequsetNew(v1,m);
//(win2.textEdit2)->setText("loading .... .... ....");
//win2.show();
}
MainWindow::~MainWindow(){
}
- main.cpp
#include "test.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
项目处理结果:
1.用户点击“打开”菜单,手动选择.iniwen文件导入
2.后台工作线程拿到文件内容的相关参数准备进行后台解析
3.数据解析前会有一个进度条对话框ProcessDialog的显示
4.进度条显示完毕,新弹窗中实时while(1)的显示解析结果
碍于繁琐,执行图片不再赘述。如有问题询问欢迎评论区留言~~