收集安群发信息[精品]
2 需求分析 2
2.1管理系统功能的需求 ..................................................................... 2
2.2管理系统性能的需求 ..................................................................... 2
2.3用户对管理系统的需求 ................................................................. 2 3 系统的
........................................................................................... 4
3.1管理系统的整体架构设计 ............................................................. 4
3.2后台数据库的设计 ......................................................................... 5
3.2.1 关于数据库中表的说明 ..................................................... 5
3.2.2 关于数据库中实体的说明 ................................................. 6
3.3开发步骤 ......................................................................................... 6
3.3.1 开发工具介绍 ..................................................................... 6
3.3.2 项目的开发原理 ................................................................. 7
3.3.3 项目的开发步骤 ................................................................. 7
3.3.4 后台数据库开发步骤 ........................................................11 4 系统的实现 ......................................................................................... 13
4.1项目开发环境的介绍 ................................................................... 13
4.2各个功能模块的具体实现方法 ................................................... 13
4.3系统主界面的美化 ....................................................................... 20 5 系统的测试 ......................................................................................... 22
5.1系统测试的必要性 ....................................................................... 22
5.2系统测试的
........................................................................... 22
5.3系统测试的结果和总结 ............................................................... 22 结论 ........................................................................................................... 25 致谢 ........................................................................................................... 26 参考文献 ................................................................................................... 27 附录 ........................................................................................................... 29
2 需求分析
随着网络技术的飞速发展,人们利用网络的途径也日趋多样化。网吧的诞生,给喜好互联网的人们带来了更多利用网络的机会。然而,凡事皆有利弊,由于网吧流动人员大等特点,给网吧的局域网埋下了诸多的隐患。像未经管理员授权私自接入主机、主机开放容易受攻击的服务等,这些安全问题都需要有一种网吧局域网管理工具,来实时的了解各个接入主机的状态信息。
2.1管理系统功能的需求
网吧主机接入状态管理系统(HSTAT GLXT)的功能需求如下:
(1)能够实时扫描到网吧在线主机的主机名、IP地址、MAC地址以及在线时间;
(2)能够将扫描到的网吧在线主机各项信息写入后台数据库;
(3)能够对写入到后台数据库的在线主机信息,按照指定的方式进行查询。
2.2管理系统性能的需求
网吧主机接入状态管理系统(HSTAT GLXT)的性能需求如下:
(1)管理系统在网吧局域网内运行时,应该尽可能少的占用网络资源;
(2)当该管理系统自身出现问题或操作无响应时,程序能以较快的速度退出;
(3)程序应该在用户能够接受的时间内完成对网吧局域网主机信息的扫描。
2.3用户对管理系统的需求
计算机网络的发展不仅仅是其本身技术的快速革新,网络的产业链效应也是巨大的,会促使其相关产业及后续部门迅猛发展,其带来的经济效益也是极其可观和不可估
[1]量的。网吧的诞生几乎是在一夜之间就遍布大街小巷,并且以其惊人的数目充满整个
网络娱乐业。由于网吧局域网的安全问题,网管人员大都会使用网吧主机管理工具来维护网吧的局域网。但是,由于使用软件的人员多为非专业人员,他们的需求也是该项目
开发时要考虑的重要部分。
网吧主机接入状态管理系统(HSTAT GLXT)的用户需求如下:
(1)对运行的软硬件环境的要求应该尽可能的低;
(2)操作界面应美观、简洁、大方;
(3)各控件位置应排列得当,便于控制。
3 系统的设计
3.1管理系统的整体架构设计
网吧主机接入状态管理系统(HSTAT GLXT)是一款能针对网吧或小型局域网采取主机管理的应用软件。采用网络低层的
,其特点是能够很有效的避开网吧内主机的安全软件,并扫描出每台在线主机的主机名称、IP地址、MAC地址和在线时间。该软件采用识别主机的物理地址即MAC地址的方法,扫描结果准确可靠。在程序运行时,占用较少的网络资源。该程序使用Microsoft Visual C++ 6.0作为开发工具。因为利用Microsoft Visual C++ 6.0编写的程序完全支持Microsoft公司的操作系统,所以用户不用
[2]安装任何插件和工具,直接操作执行文件即可。
由于网吧规模的大小不尽相同,所以对软件的扫描速度有一定的要求。对较大规模的网吧,其主机数目过多对扫描的速度是一个考验,应该在操作人员能够接受的范围内,不能因为扫描过慢而让用户误认为操作无响应。为了解决对网吧主机网络信息探测扫描的速度问题,本程序利用在一个进程下开启线程(可以是多个进程)的方法来提高扫描速度。
我们从操作系统的知识了解到,所谓进程是程序在一个数据集合上运行的过程,它是操作系统进行资源分配和调度的一个独立单位。线程是指进程中某个单一顺序的控制
[3]流,也被称为轻型进程,一个进程可包含多个线程。也就是说当程序开始运行时,其实启动相应进程的同时也启动了该进程下的线程。若进程下包含多个线程,这些线程同时工作可以提高程序的执行速度。
当软件在操作系统中运行时,后台至少会开放一个主线程在执行,开放的这个线程用户是无法干预的,如果用户要提高程序的运行效率可以除此之外,另外再创建多个线程使它们同时运行在一个进程里。线程在计算机中运行时需要得到操作系统内核和中央处理器的支持,像某个进程中线程的建立、撤销和切换都是如此。如果是多个线程同时运行时,可以减少计算机中央处理器的处理时间。事实上,在具体执行多个线程时,中央处理器会为进程中的每一个线程分配一段处理器时间,计算机的操作系统使用一种叫做时间片轮转的算法来轮流分配给各线程时间,对于外界宏观的操作者来说会误认为是
[4]多个线程并发的执行。所以在各个线程之间为了争取中央处理器的使用权时,势必会消耗操作系统的资源从而影响软件的稳定性。由于网吧局域网的规模较小,所以在对项目进行开发时只创建一个线程。
根据毕业设计题目的要求,网吧主机接入状态管理系统(HSTAT GLXT)是基于TCP/IP协议栈的系统。通常人们所讲的四层网络体系结构就是TCP/IP的体系结构,由网络低层到高层分别包括网络接口层、网际层、运输层和应用层,该体系结构每一层都包含有很多协议并不是单指TCP协议和IP协议,两个体系结构之间的对等层使用相同的协议来传输信息,从外界看很像是数据结构中所讲的“栈(stack)”,所以被叫做TCP/IP
[5]协议栈。
在该管理系统中最为核心的任务是需要获得局域网内各个主机所对应的MAC地址。在TCP/IP协议族中,IP协议是最为核心的协议之一,与IP协议配合使用的ARP协议就可以完成软件所需的功能。ARP(Address Resolution Protocol)被称作地址解析协议,可以实现同一个局域网内的计算机或路由器的IP地址和物理地址之间的映射。在设计的系统中使用了该协议来完成所需功能。
对于该项目各模块的大致规划,基本符合软件工程中的开发理念。项目中总体包含有5个功能模块,分别是本机信息模块、在线主机信息模块、日历及时间模块、实用工具模块和主机信息精确查找模块。将各个模块之间的联系降至最小,增强各个模块内部的聚合性,以便达到良好的独立性,从而增强软件的可用性。在对项目主界面的总体规划后,将各模块中的控件安排在适当的位置,使系统有更好的人机交互。具体的功能模块图详见图3.1。
3.2后台数据库的设计
3.2.1 关于数据库中表的说明
网吧主机接入状态管理系统(HSTAT GLXT)对网吧所在局域网进行扫描后所得信息应该能够写入相应的后台数据库中。由于考虑到这款管理工具的实用、高效、简易等特点,所以数据库软件采用Microsoft Office Access 2003进行设计。在此数据库工具中建立一个名为“主机状态”的数据库文件,并在其中利用设计器新建一张名为“在线主机信息”的表格,用来存放网吧内各在线主机的网络信息。表中各字段名称和数据类型详见表3.1。
网吧主机接入状态
管理系统
(HSTAT GLXT)
主机信息精确本机信息在线主机信息日历及时间实用工具查找显示本机获得网吧在线网吧在线网吧在线输入IP地址显显示本机获得系统日期名和OS信主机网络信息主机信息主机信息示对应MAC地网络信息和时间并显示息并显示入库查询址
按MAC地址显示库中
查询查询结果
图3.1 HSTAT GLXT模块图
表3.1 在线主机信息表各字段参数
字段名称 数据类型 字段大小 备注
序号 自动编号 长整形 主键
主机名称 文本 20个字符 —
IP地址 文本 20个字符 —
MAC地址 文本 50个字符 —
在线时间 文本 50个字符 — 3.2.2 关于数据库中实体的说明
通常在建立数据库时都要先对数据库的大体结构进行逻辑上的规划,并描述出各实体的具体属性等信息,在该管理系统后台的主机状态数据库中,仅包含有一个实体和关于该实体的四个属性。其逻辑结构如图3.2所示。
在线主机信息
在线时间主机名称IP地址MAC地址
图3.2 HSTAT GLXT后台数据库的实体属性图 3.3开发步骤
3.3.1 开发工具介绍
制作该系统所用的开发工具是Microsoft Visual C++ 6.0(简称VC6.0)。此开发工具是于20世纪90年代推向计算机市场的一款基于C++语言的软件开发工具,主要支持的
[6]。VC6.0相比之前的软件操作系统有 Windows 2000、Windows NT 4.0和Windows XP有很多特点,在该工具中可以进行基于Windows OS的可视化编程,其内部有可视化的集成开发环境(IDE),可谓是熟悉C++语言的编程者之首选工具。此外,在使用该工具编程时,不仅可以进行整体编译查找错误,而且支持添加断点进行逐步查错,从而提高了编程效率。
在该软件中集成了微软公司所提供的基础类库MFC(Microsoft Foundation Classes)并且以C++类的方式来封装了Windows的API(Application Programming Interface)函数。API只是一些Windows下提供的应用程序编程语言的接口(即一些函数),而MFC
[7]提供了很多应用程序的框架、Windows的控件、组件和封装好的函数。为编程人员减轻了不少的负担。
MFC尽管是Windows API与C++语言的完美结合,但这仍然改变不了VC6.0中出现的一些问题。如封装的函数过少,支持模块的能力比较差,经常出现编译“假死”现象。所以,目前较新的操作系统与之兼容性不是很好。 3.3.2 项目的开发原理
该管理系统的主要功能,是能够实现在网吧构建的小型局域网内扫描出所有在线主机的网络信息,并能显示本机的网络信息和本地信息,最主要的是能够获得某个IP地址所对应的物理地址。这里主要是利用TCP/IP协议族中的ARP协议来实现,ARP即地址解析协议,它可以通过向局域网内发送ARP数据探测包来获得某个IP地址所对应的
[8]物理地址。考虑到程序工作速度的问题,我们可以通过在当前进程中另外开启一个线程。最后,将结果存入后台的数据库。
3.3.3 项目的开发步骤
首先,打开Microsoft Visual C++ 6.0开发工具新建一个工程(HSTAT GLXT),选择基于对话框的类,并且勾选支持Windows Sockets和MFC风格的对话框。如图3.3所示。
图3.3 新建名为HSTAT GLXT的工程 进入到主界面后根据预先的构思将所需控件摆放至合适的位置,更改各个控件的名
称和属性。因为控件较多,为了有更好的显示效果,应该预先调整好控件的大小。具体
控件名称及相关信息如表3.2所示。
表3.2 程序所需主要控件及对应变量
控件名称 类型 对应变量名 中文名称
— — 扫描在线主机 IDC_BUTTON_HOSTSCAN
— — 清空信息列表 IDC_BUTTON_EMPTY
— — 精确查找 IDC_BUTTON_GETMAC
— — 写入数据库 IDC_BUTTON_INSERT_DB
— — 历史数据查找 IDC_BUTTON_SEARCH
— IDC_COMBO _ADDR CComboBox m_comAddr
— IDC_EDIT_ADDR2 CString m_strAddr2
— IDC_EDIT_GATE CString m_strGate
— IDC_EDIT_MAC CString m_strMac
— IDC_EDIT_ MAC2 CString m_strMac2
— IDC_EDIT_ NAME CString m_strName
— IDC_EDIT_ SUB CString m_strSub
— IDC_EDIT_ VERSION CString m_strVersion
— IDC_LIST_ HOSTMSG CListCtrl m_ctlList
— IDC_PROGRESS1 CProgressCtrl m_progress
— — 设初始值为0 IDC_STATIC_TIME
由于在 VC6.0中封装了很多API函数,所以我们在调用时是十分方便的,可以帮助
实现需求分析中预期的功能。工程中所需类和变量如图3.4所示。
图3.4 HSTAT GLXT中所有的类与变量
本机信息模块中,通过编写合适的算法并调用开发环境中封装好的库函数,使系统显示出本机的计算机名、操作系统名、IP地址、MAC地址、网关地址和子网掩码。如果网络环境初始化不成功,则无法获取信息,需要重新开始。由于VC6.0中有日期时间控件,所以可直接拖动该控件获取系统当前数据。详细流程如图3.5所示。
在线主机信息模块中,通过借助TCP/IP协议族中的ARP协议来向网吧局域网内发送信息从而获得网络中IP地址对应的物理地址。如果网络环境初始化不成功,则无法获取信息,需要重新开始。扫描后的主机信息应能写入数据库,并且可以按照MAC地址进行查询,如果查询结果为空,就结束程序。详细流程如图3.6所示。
开始
初始化用户界面N
Y是否成功,
初始化网络环境
N
Y是否成功,显示本机
网络信息
获取本机网络信息
图3.5 本机信息模块流程图
开始
结束
初始化用户界面N
Y是否成功?
初始化网络环境N
Y显示扫描是否成功?结果
扫描网吧在线主机
写入数据库
根据MAC地址查询
Y记录 显示查询
结果图3.6 在线主机信息模块流程图
N结果是否为空?主机信息精确查找模块,是为了方便对网吧内某台主机的MAC地址进行查找,以
结束
便在数据库中查询记录时用到。如果网络环境初始化不成功,则无法获取信息,需要重新开始。并且如果输入的IP地址为空,则不会返回结果。详细流程如图3.7所示。
开始
初始化用户界面
N
Y是否成功,
初始化网络环境
N
Y是否成功,
输入目标IP地址
Y主机信息精确查找
结果是否为空,
N显示对应的
MAC地址
图3.7 主机信息精确查找模块流程图 3.3.4 后台数据库开发步骤
此程序的后台数据库采用的是Microsoft Office Access 2003数据库应用软件,因为
结束管理系统需要有高效、准确、实用的特点,所以选择较小的数据库可以减轻系统的负担,运行起来效率较高。Access有很多自己的闪光点。
首先,对于较小的程序,此数据库由于较小并且功能强大,对系统的负担也较小,是初学者的首选。
其次,它也是一款基于图形界面操作的数据库,并且支持SQL语句对库的操作,人机交互性较好。
最后,Access数据库在操作时能尽量减少代码量,相对减轻了对应用程序空间占用
[9]的负担,同时支持微软推出的很多编程工具。像本毕业设计所用的VC6.0开发工具。
具体的后台数据库表的建立如图3.8所示。
图3.8 建立在线主机信息表
4 系统的实现
4.1项目开发环境的介绍
硬件环境要求主要针对的是开发编程人员所用的计算机,硬件方面应尽可能地高
[10]端,因为这样方便在编译、调试中很快找出问题,且能在后期测试时较少时间的开销。各硬件指标如下:
(1)中央处理器(CPU):至少应在Pentium PIII及以上,频率为1GHz或更快;
(2)内存:至少应在1GB(32位)及以上;
(3)网络环境:各种类似于网吧环境的局域网(应具备有交换机、路由器等)。
软件环境主要是在开发项目时,该程序所要用的编程工具和其它应用软件等。此管理系统由于所占内存空间较小,所以对软件要求也相对的较低。
(1)计算机的操作系统:Windows XP;
(2)后台数据库:Microsoft Office Access 2003;
(3)开发所使用的软件:Microsoft Visual C++ 6.0。 4.2各个功能模块的具体实现方法
根据在前期规划中所设计的5个功能模块,分别为本机信息模块、在线主机信息模块、日历及时间模块、实用工具模块和主机信息精确查找模块,将这些模块整体布局好后主界面如图4.1所示。
本机信息模块的实现主要是在系统提供的OnInitDialog( )类中进行的,分别通过库函数gethostname( )、GetVersionEx( )、GetAdaptersInfo( )和结构体PIP_ADAPTER_INFO、OSVERSIONINFO,来获得计算机的本地信息和网络信息。值得注意的是,在识别操作系统的类型时,应该注意判断语句的编写。该模块运行后的界面如图4.2所示。详细代码见附录,主要的函数实现代码如下:
BOOL CHSTATGLXTDlg::OnInitDialog()
{
DWORD dwLen = 0, dwError;
dwError = GetAdaptersInfo(NULL, &dwLen);
图4.1 HSTAT GLXT布局后的主界面 pIPHelper = (PIP_ADAPTER_INFO)malloc(dwLen); dwError = GetAdaptersInfo(pIPHelper, &dwLen); CString strMAC;
strMAC.Format("%02X-%02X-%02X-%02X-%02X-%02X",pIPHelper->Address[
0],\
pIPHelper->Address[1], pIPHelper->Address[2], pIPHelper->Address[3],\
pIPHelper->Address[4], pIPHelper->Address[5]); PIP_ADDR_STRING pAddrList = &pIPHelper->IpAddressList; CString m_IpAddress="";
while(pAddrList != NULL)
{
CString strAddr = pAddrList->IpAddress.String;
pAddrList = pAddrList->Next;
m_comAddr.AddString(strAddr);
}
CString strSubMask, strGateway;
strSubMask.Format("%s", pIPHelper->IpAddressList.IpMask.String);
strGateway.Format("%s", pIPHelper->GatewayList.IpAddress.String);
m_strMac = strMAC;
m_strSub = strSubMask;
m_strGate = strGateway;
m_comAddr.SetCurSel(0);
char szHostName[MAX_PATH + 1];
gethostname(szHostName, MAX_PATH);
m_strName = szHostName;
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&os);
m_strVersion = strOS;
UpdateData(FALSE);
}
图4.2 本机信息模块运行结果图
同样,日历及时间模块也需要在OnInitDialog( )函数中编写。由于API函数中已经
封装有关于时间的函数,再加上MFC风格的图形界面中有现成的日历控件,可以随取
随用。所以,代码较为简单。而主机信息精确查找模块则需要在OnButtonGetmac( )函数
中编写,在程序中应注意对输入的IP地址进行合法性判断,部分代码如下,详细代码
见附录。其运行界面如图4.3所示。
void CHSTATGLXTDlg::OnTimer(UINT nIDEvent) {
SYSTEMTIME sti;
GetLocalTime( &sti );
time.Format("%d:%d:%d", sti.wHour, sti.wMinute, sti.wSecond);
GetDlgItem(IDC_TIME)->SetWindowText(time);
CDialog::OnTimer(nIDEvent);
}
void CHSTATGLXTDlg::OnButtonGetmac()
{
UpdateData(TRUE);
unsigned long ulAddr = inet_addr(m_strAddr2);
unsigned long ulMAC[2];
unsigned long ulLen = 6;
DWORD dwRetVal = SendARP(ulAddr, 0, ulMAC, &ulLen);
if(dwRetVal == NO_ERROR)
{
size_t i, j;
char * szMac = new char[ulLen*3];
PBYTE pbHexMac = (PBYTE)ulMAC;
for (i = 0, j = 0; i < ulLen - 1; ++i)
{
j += sprintf (szMac + j, "%02X:", pbHexMac[i]);
}
sprintf (szMac + j, "%02X", pbHexMac[i]);
m_strMac2 = szMac;
delete [] szMac;
}
UpdateData(FALSE);
}
图4.3 日历及时间模块与主机信息精确查找模块运行图 其次,在线主机信息模块,也是该项目中最为核心的模块,它是在OnHostscan( )
主函数中进行代码的编写,通过库函数SendARP ( )、gethostbyaddr( )和GetCurrentTime( )
[11]来获得网吧局域网内的主机网络信息。部分代码如下,全部代码详见附录。运行结果
如图4.4所示。
void CHSTATGLXTDlg::OnHostscan()
{
CString destIp = pInfo->IpLeft + pInfo->IpRight;
IPAddr ipAddr = inet_addr(destIp);
ULONG Mac[2];
memset (Mac, 0xff, sizeof (Mac));
ULONG MacLen = 6;
DWORD ret = SendARP (ipAddr, 0, Mac, &MacLen);
strMac.Format("%02X-%02X-%02X-%02X-%02X-%02X",p[0],p[1],p[2],p[3],p[4]
,p[5)
struct hostent FAR * host;
host = gethostbyaddr((LPSTR) &ipAddr,4,AF_INET);
CString strName;
if(host == NULL) strName = "Unknown";
else strName = host->h_name;
Msg[nCount].Ip = destIp;
Msg[nCount].Mac = strMac;
Msg[nCount].Name = strName;
CTime m_CurrentTime=CTime::GetCurrentTime();
CString m_StrTime;
m_StrTime.Format("%ld-%ld-%ld%ld:%ld:%ld",m_CurrentTime.GetYear(),
m_CurrentTime.GetMonth(),m_CurrentTime.GetDay(),m_CurrentTime.GetHour(),
m_CurrentTime.GetMinute(),m_CurrentTime.GetSecond());
Msg[nCount].Onlinetime =m_StrTime;
}
图4.4 在线主机信息模块运行图
最后,在实用工具模块中,将从网吧局域网中获取的在线主机信息写入到后台数据
库表中,这一步需要使用ADO进行操作。微软公司在API函数中提供的ADO(ActiveX
[12]Data Objects)数据对象,来实现对后台数据库的操作。其中的部分代码如下,全部
代码详见附录。运行结果如图4.5所示。
void CHSTATGLXTDlg::OnButtonInsertDatabase()
{
CMyAdo m_wndAdo;
m_wndAdo.OnInitADOConn(CMyAdo::m_StrAccess);
temp=_T("select * from 在线主机信息");
m_wndAdo.pRecordset=m_wndAdo.OpenRecordset(temp);
for(int i=0;i
AddNew();
m_wndAdo.pRecordset ->PutCollect("主机名称",(_bstr_t)Msg[i].Name);
m_wndAdo.pRecordset ->PutCollect("IP地址",(_bstr_t)Msg[i].Ip);
m_wndAdo.pRecordset ->PutCollect("MAC地址",(_bstr_t)Msg[i].Mac);
m_wndAdo.pRecordset ->PutCollect("在线时间",(_bstr_t)Msg[i].Onlinetime);
m_wndAdo.pRecordset ->Update();
}
m_wndAdo.CloseRecordset();
m_wndAdo.CloseConnection();
AfxMessageBox(_T("扫描数据已成功写入数据库!")); }
void CHSTATGLXTDlg::OnButtonSearch() {
CSearchDialog m_wndSearch;
m_wndSearch.DoModal();
}
图4.5 扫描信息写入数据库表
4.3系统主界面的美化
一款好的应用软件,在其所有的功能实现之后,还应该对各个界面和页面。特别是
对主界面进行一定程度的美化,这样才能够吸引用户,从而提高应用软件的用户友好性。相反,由于编程软件和开发工具的局限性,并不能为用户集成令人满意的皮肤或更多的背景图片。若不对界面进行美化,会造成用户在长时间使用该工具后,对此类软件的一种乏味,这也从一定程度上降低了使用该管理工具人员的工作效率。通常,对软件前台的美化主要是颜色的使用和图片的添加,如加入版权信息、设置个性的LOGO、添加艺术字标题等。那么,对网吧主机接入状态管理系统(HSTAT GLXT)主界面的美化,主
要包括版权信息和标题背景图片两部分。
首先,版权信息的制作主要在VC6.0中进行,其中日历及时间模块中显示系统时间的图标制作过程与之相似。利用编程软件自带的画图功能,为该管理系统制作一个LOGO图标,使用画笔在网格中绘制本人姓名中各汉字的拼音首字母,并保存成位图格式。之后,在主界面中拖入图片控件,并引入名为IDB_BITMAP_LOGO的图片且调整好尺寸即可,再在图片旁边拖入静态文本框写入版权信息,如图4.6所示。
然后,对标题背景图片的制作,主要借助软件Adobe Photoshop CS3来完成。精选一张背景图片在该软件中打开,在图片中加入“网吧主机接入状态管理系统”这几个字并将其保存成位图格式。并在VC6.0中主界面相应位置拖入图片控件,然后将名为IDB_BITMAP_BIAOTI图片引入后调整好尺寸即可。标题背景图片如图4.7所示。
图4.6 系统版权信息
图4.7 系统主界面标题图片
5 系统的测试
5.1系统测试的必要性
对网吧主机接入状态管理系统(HSTAT GLXT)的后期测试,主要是为了验证该系统在前期规划设计过程中所提到的功能是否实现,在标准的环境下,是否能够正常运行,扫描出,类似于像网吧局域网中各个上线主机的网络信息。并能将这些信息写入到后台的数据库中,在必要时是否能够根据MAC地址很快速的检索出历史数据。经过一些设置好的特殊数据测试时,该管理系统是否能够发现问题,并弹出提示对话框。如果经过反复的测试后,暴露出问题,说明系统不是足够的稳定,还需要进一步的优化,通过反
[13]复对发现的BUG进行修补,系统才会进一步的稳定。如果在网络因安全问题出现瘫痪时,像全网中病毒、被黑客攻击等,需要用此类工具对全网络进行态势感知,来帮助
[14]修复网络,此时如果软件出现问题,将是十分被动的。所以说,反复的进行这种后期测试是十分有必要的。
5.2系统测试的方案
首先,是测试地点的选择,由于学校没有合适的且闲置的网络环境,出于安全考虑,也不可能在真实的网吧进行实地测试,故,地点选在寝室来进行。
其次,是对测试环境软硬件的要求,测试本机应装有VC6.0开发软件,要有小型交换机一台和双绞线若干,便于组建模拟网吧环境的网络。
最后,关于测试的方法可分为两部分,第一部分是采用在管理系统的编程环境下进行的,加入断点来对各个模块逐一测试。然后在开发人员的计算机上运行,就是人们所说的白盒测试的方法;第二部分是首先利用校园网进行测试,然后再断开校园网,由寝室同学协助,利用双绞线、交换机和6台计算机来搭建一个模拟环境,来模仿网吧的局域网环境,即通常所说的黑盒测试。
5.3系统测试的结果和总结
经过运用多种方法对网吧主机接入状态管理系统(HSTAT GLXT)进行测试,结果表明基本达到了该项目初期所规划设计的效果,各项功能均可实现。完成了毕业设计任
务书中对该项目的要求,能获得类似于网吧局域网内上线主机的网络信息,并能将所得信息存入数据库,可以按照MAC地址对记录进行查询,如图5.1所示。除此之外界面上还能相当智能的识别出本机的网络信息、操作系统类型和主机名,系统运行结果如图
5.2所示。
图5.1 历史数据的查询结果
图5.2 HSTAT GLXT运行结果图
虽然该管理系统在现阶段经过了后期测试,但是任何软件在将来使用时,由于网络环境等诸多因素的影响,一些隐藏的错误还会暴露出来,出现这样或那样的问题。然而,
这些问题将在不断地完善中得到解决。从来没有一款软件经过测试完全排除错误,保证
[15]万无一失,这是不现实也是不可能的。网吧主机接入状态管理系统(HSTAT GLXT)
也是如此,有待实践的检验。
结论
在计算机网络技术日新月异的时代,网吧成为人们休闲的场所。但是,由于网吧自身缺陷和监管漏洞,网吧的局域网存在着安全隐患。如果有能对网吧的主机进行管理的工具,就会大大降低网吧的风险。因此,在本次毕业设计中尝试开发了“网吧主机接入状态管理系统(HSTAT GLXT)”,不仅是对个人能力的挑战,同时也丰富了专业知识并提高了专业技能,为以后的工作积累了不少经验。故,我应该认真的总结此次毕业设计的得与失。
从本次的毕业设计中,经过查阅资料,对开发环境Microsoft Visual C++ 6.0的优点以及Microsoft API函数有了较为详细的了解,如提供了很多简易的接口、比较漂亮的图形界面和控件等。并且发现了Microsoft Visual C++ 6.0软件的某些弊端,如编译运行死锁、封装的函数过少等都给开发人员带来了诸多不便。
此外,在本次毕业设计中,还存在不少应该改进的地方和问题,例如系统在没有运行结果时应该弹出对话框、扫描主机信息速度慢,这两点做的不够智能应改进。在连接数据库方面,本人只是调用别人封装好的类,由于我的专业是网络工程,对软件工程方面的知识不是很精通,并不知晓如何编写这种类,所以今后应学会编写封装类和函数。在开发过程中体会到了自己知识储备不够,平时开发的经验也少,从而造成了进度缓慢等问题。但是,我以一名大学生的良知,告诉自己一定要走完这段路。
最后,祝福自己能顺利毕业,踏上更远的征途。
致谢
此毕业设计说明书是在充分查阅相关资料的基础上完成撰写的,因为是初次写此类型题目的说明书,所以内容未免有些不成熟。在编写过程中,遇到疑难问题时,多有导师指导。在此我仅代表个人,向尊敬的孙飞显老师致以真诚的敬意和谢意,感谢他用渊博的知识、敏捷的思维、严谨的学风、待人宽厚的品德来帮助我解决各种问题,在指导老师这种品德和行为的感召下,使我开阔了眼界,丰富了学识,让人受益匪浅。
感谢小组的其他同学帮助调试程序,并给出意见和建议,使得我在较短的时间内调试完成了毕业设计作品。同时,对在幕后默默支持我的家人致以深深的谢意。
最后,还要感谢在百忙之中来参加评审我毕业设计说明书的老师,希望审阅老师能多提宝贵意见。
参考文献
[1] 肖朝晖,罗娅.计算机网络基础[M].北京:清华大学出版社,2011(
[2] 辛长安,梅林.VC++编程技术与难点解析[M].北京:清华大学出版社,2002.
[3] 许曰滨,孙英华等.计算机操作系统[M].北京:北京邮电大学出版社,2007.
[4] 腾英岩.多核多线程技术[M].大连:东软电子出版社,2012. [5] 罗军周.TCP/IP协议及网络编程技术[M].北京:清华大学出版社,2010.
[6] 王正军.Visual C++6.0程序设计从入门到精通[M].北京:人民邮电出版社,2006.
[7] 侯俊杰.深入浅出MFC[M].武汉:华中科技大学出版社,2001. [8] 罗莉琴,詹祖桥.Windows网络编程[M].北京:人民邮电出版社,2011(
[9] 刘卫国.Access数据库基础与应用[M].北京:北京邮电大学出版社,2011.
[10] 孙知信.网络异常流量识别与监控技术研究[M].北京:清华大学出版社,2010.
[11] 陈国建,杨国祥,唐清荣等.Visual C++范例开发大全[M].北京:清华大学出版社,2010.
[12] 管西京.深入体验VC++项目开发[M].北京:清华大学出版社,2011.
[13] Meyer, BertrandObject.Oriented Software Construction.PrenticeHall, 1988.
[14] P. Johnson-Laird, Situation Awareness for Cyber Defense, Oxford University Press,
2006.
[15] Ford, W, Computer Communications Security, Englewood Cliffs[M].NewJersey, Prentic
Hall, 1994.
附录 ////////////////////////////////////////////////////////////////////////////////////////////stdafx.h
#include
#include
#include
#include
#ifndef _AFX_NO_AFXCMN_SUPPORT #include
#pragma once
#include
#include "IPhelper/Iphlpapi.h"
#pragma comment(lib, "IPhelper/IPHLPAPI.LIB") #pragma comment(lib, "ws2_32.lib") #import "C:\Program Files\Common Files\system\ado\msadox.dll" no_namespace
#import "C:/Program Files/Common Files/System/ADO/msado15.dll" named_guids
rename("EOF","adoEOF"), rename("BOF","adoBOF") using namespace ADODB;
#define WM_MYMSG WM_USER+136
////////////////////////////////////////////////////////////////////////////////////////////HSTAT GLXTDlg.h : header
file
#include
#include
using namespace std;
struct IpInfo
{
CString IpLeft;
CString IpRight;
int nThread;
};
struct IpMsg
{
CString Ip;
CString Name;
CString Mac;
CString Onlinetime;
};
extern CRITICAL_SECTION m_cs;extern IpInfo Info[255];
extern CDialog* pDlg;
extern int nCount;
CString GetIP();
DWORD WINAPI ScanThread (PVOID pParam);
////////////////////////////////////////////////////////////////////////////////////////////HSTAT GLXTDlg.cpp :
implementation file
#include "stdafx.h"
#include "fstream.h"
#include "math.h"
#include "HSTAT GLXT.h"
#include "HSTAT GLXTDlg.h" #include"SearchDialog.h"
#ifndef MY_ADO
#include"MyAdo.h"
PIP_ADAPTER_INFO pIPHelper = NULL; CString strIp;
IpInfo Info[255];
IpMsg Msg[255];
CDialog* pDlg;
CRITICAL_SECTION m_cs;
int nCount;
int ThreadNum;
CHSTATGLXTDlg::CHSTATGLXTDlg(CWnd* pParent /*=NULL*/)
: CDialog(CHSTATGLXTDlg::IDD, pParent) {
pDlg = this;
InitializeCriticalSection(&m_cs);
AfxOleInit();
}
CHSTATGLXTDlg::~CHSTATGLXTDlg() {
DeleteCriticalSection(&m_cs); }
BOOL CHSTATGLXTDlg::OnInitDialog() {
m_ctlList.InsertColumn(0,"序号",LVCFMT_LEFT,36);
m_ctlList.InsertColumn(1,"主机名称",LVCFMT_LEFT,102);
m_ctlList.InsertColumn(2,"IP 地址",LVCFMT_LEFT,94);
m_ctlList.InsertColumn(3,"MAC地址",LVCFMT_LEFT,118);
m_ctlList.InsertColumn(4,"在线时间",LVCFMT_LEFT,134);
strIp = GetIP();
if(strIp == "") ::MessageBox(NULL,"获取本机IP失败!","",MB_OK);
else
{
int nPos = strIp.ReverseFind('.');
CString TargetIp = strIp.Left(nPos) + "." + "0";
m_strTarget = TargetIp;
UpdateData(FALSE);
}
DWORD dwLen = 0, dwError;
dwError = GetAdaptersInfo(NULL, &dwLen);
pIPHelper = (PIP_ADAPTER_INFO)malloc(dwLen);
dwError = GetAdaptersInfo(pIPHelper, &dwLen);
CString strMAC;
strMAC.Format("%02X-%02X-%02X-%02X-%02X-%02X", pIPHelper->Address[0],\
pIPHelper->Address[1], pIPHelper->Address[2], pIPHelper->Address[3],\
pIPHelper->Address[4], pIPHelper->Address[5]);
PIP_ADDR_STRING pAddrList = &pIPHelper->IpAddressList;
CString m_IpAddress ="";
while(pAddrList != NULL)
{
CString strAddr = pAddrList->IpAddress.String;
pAddrList = pAddrList->Next;
m_comAddr.AddString(strAddr);
}
CString strSubMask, strGateway;
strSubMask.Format("%s", pIPHelper->IpAddressList.IpMask.String);
strGateway.Format("%s", pIPHelper->GatewayList.IpAddress.String);
m_strMac = strMAC;
m_strSub = strSubMask;
m_strGate = strGateway;
m_comAddr.SetCurSel(0);
free(pIPHelper);
char szHostName[MAX_PATH + 1];
gethostname(szHostName, MAX_PATH);
m_strName = szHostName;
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
CString strOS;
if(os.dwPlatformId == 0)
{
strOS = "Win32";
}
else if(os.dwPlatformId == 1)
{
if(os.dwMinorVersion == 0) strOS = "Windows 95 ";
else if(os.dwMinorVersion == 10) strOS = "Windows 98 ";
strOS += os.szCSDVersion;
}
else if(os.dwPlatformId == 2)
{
if(os.dwMajorVersion ==3)
{
strOS = "Windows NT 3.51";
}
else if(os.dwMajorVersion == 4)
{
strOS = "Windows NT 4.0";
}
else if(os.dwMajorVersion == 5)
{
if(os.dwMinorVersion == 0) strOS = "Windows 2000 ";
else if(os.dwMinorVersion == 1) strOS = "Windows XP ";
else if(os.dwMinorVersion == 2) strOS = "Windows Server 2003 ";
}
else if(os.dwMajorVersion == 6)
{
if(os.dwMinorVersion == 0) strOS = "Windows Vista ";
else if(os.dwMinorVersion == 1) strOS = "Windows 7 ";
}
strOS += os.szCSDVersion;
}
m_strVersion = strOS;
UpdateData(FALSE);
SYSTEMTIME sti;
GetLocalTime( &sti );
time.Format("%d:%d:%d", sti.wHour, sti.wMinute, sti.wSecond);
GetDlgItem(IDC_TIME)->SetWindowText(time);
SetTimer(1,1000,NULL);
return TRUE;
}
BOOL CHSTATGLXTDlg::OnMyMsg(WPARAM wp,LPARAM lp) {
int nRow = wp;
CString strNo;
strNo.Format("%d",nRow + 1);
CString strPrint;
strPrint.Format("destIp is %s",Msg[nRow].Ip);
OutputDebugString(strPrint);
m_ctlList.InsertItem(nRow,strNo);
m_ctlList.SetItemText(nRow,1,Msg[nRow].Name);
m_ctlList.SetItemText(nRow,2,Msg[nRow].Ip);
m_ctlList.SetItemText(nRow,3,Msg[nRow].Mac);
m_ctlList.SetItemText(nRow,4,Msg[nRow].Onlinetime);
UpdateData(FALSE);
return TRUE;
}
void CHSTATGLXTDlg::OnButtonGetmac() {
UpdateData(TRUE);
if(m_strAddr2.IsEmpty())
{
AfxMessageBox("对不起,IP地址不能为空,请您输入相应的IP地址!");
return;
}
if(strlen(m_strAddr2)>15)
{
AfxMessageBox("IP地址有误(总长度不能超过15位),请输入规范的IP地址!");
return;
}
int dotnum = 0;
int len;
len = strlen(m_strAddr2);
for(int i = 0; i3)
{
AfxMessageBox("IP地址每个字段数字位数不能超过3位! 请检查IP地址!");
return;
}
switch(len)
{
case 3:
{
while(len!=0)
{
ip[i] += (temp[i][len-1]-48) *pow(10, 3-len);
len--;
}
break;
}
case 2:
{
while(len!=0)
{
ip[i] += (temp[i][len-1]-48) *pow(10, 2-len);
len--;
}
break;
}
default:
{
while(len!=0)
{
ip[i] += (temp[i][len-1]-48) *pow(10, 1-len);
len--;
}
}
}
}
if(ip[0]<1)
{
AfxMessageBox("IP地址首字段不能为0! 请检查IP地址!");
return;
}
for(i = 0; i<4; i++)
{
if(ip[i]>255)
{
AfxMessageBox("IP地址每个字段数字不能超过255! 请检查IP地址!");
return;
}
}
unsigned long ulAddr = inet_addr(m_strAddr2);
unsigned long ulMAC[2];
unsigned long ulLen = 6;
DWORD dwRetVal = SendARP(ulAddr, 0, ulMAC, &ulLen);
if(dwRetVal == NO_ERROR)
{
size_t i, j;
char * szMac = new char[ulLen*3];
PBYTE pbHexMac = (PBYTE)ulMAC;
for (i = 0, j = 0; i < ulLen - 1; ++i)
{
j += sprintf (szMac + j, "%02X:", pbHexMac[i]);
}
sprintf (szMac + j, "%02X", pbHexMac[i]);
m_strMac2 = szMac;
delete [] szMac;
}
UpdateData(FALSE);
}
void CHSTATGLXTDlg::OnHostscan() {
m_ctlList.DeleteAllItems();
m_strEdit = "开始检测";
UpdateData(FALSE);
nCount = 0;
if(strIp == "") ::MessageBox(NULL,"获取本机IP失败!","",MB_OK);
else
{
int nPos = strIp.ReverseFind('.');
CString IpLeft = strIp.Left(nPos) + ".";
for(int i = 0; i < 254; i ++)
{
Info[i].IpLeft = IpLeft;
CString strRight;
strRight.Format("%d",i+1);
Info[i].IpRight = strRight;
}
HANDLE hThread[255] = {0};
for(int j = 0; j < 254; j ++)
{
Info[j].nThread = j+1;
hThread[j] = CreateThread(NULL,0,ScanThread,&Info[j],0,NULL);
}
CString strPrint2;
strPrint2 = "等待线程结束";
int nThreads = 254;
int tempMax = 0;
while( nThreads >= 64)
{
nThreads = nThreads - 64;
WaitForMultipleObjects(64, &hThread[tempMax], TRUE, INFINITE);
tempMax = tempMax + 64;
}
WaitForMultipleObjects(nThreads, &hThread[tempMax], TRUE, INFINITE);
for(int k = 0; k < 128; k ++)
{
CloseHandle(hThread[k]);
}
while(ThreadNum > 0)
{
Sleep(1000);
}
CString buf;
buf.Format("检出设备:%d",nCount);
m_strEdit = buf;
UpdateData(FALSE);
}
int i = 0;
CString str;
while( i <= 100)
{
m_progress.SetPos( i );
str.Format("%d", i);
GetDlgItem( IDC_STATIC_TIME )->SetWindowText( str );
i ++;
Sleep(40);
}
}
DWORD WINAPI ScanThread (PVOID pParam) {
IpInfo* pInfo = (IpInfo*)pParam;
CString destIp = pInfo->IpLeft + pInfo->IpRight;
IPAddr ipAddr = inet_addr(destIp);
ULONG Mac[2];
memset (Mac, 0xff, sizeof (Mac));
ULONG MacLen = 6; //DWORD ret;
DWORD ret = SendARP (ipAddr, 0, Mac, &MacLen);
if(ret==NO_ERROR)
{
BYTE MacAddr[6]="";
PBYTE pbMac = (PBYTE)Mac;
for (ULONG i=0; ih_name;
EnterCriticalSection(&m_cs);
Msg[nCount].Ip = destIp;
Msg[nCount].Mac = strMac;
Msg[nCount].Name = strName;
CTime m_CurrentTime=CTime::GetCurrentTime();
CString m_StrTime;
m_StrTime.Format("%ld-%ld-%ld %ld:%ld:%ld",m_CurrentTime.GetYear(),m_Cur
rentTime.GetMonth(),m_CurrentTime.GetDay(),m_CurrentTime.GetHour(),m_Curr
entTime.GetMinute(),m_CurrentTime.GetSecond());
Msg[nCount].Onlinetime =m_StrTime;
::PostMessage(pDlg->m_hWnd,WM_MYMSG,(WPARAM)nCount,(LPARAM)0);
nCount++;
LeaveCriticalSection(&m_cs);
}
return 0;
}
void CHSTATGLXTDlg::OnButtonEmpty()
{
m_ctlList.DeleteAllItems();
}
void CHSTATGLXTDlg::OnTimer(UINT nIDEvent) {
SYSTEMTIME sti;
GetLocalTime( &sti );
time.Format("%d:%d:%d", sti.wHour, sti.wMinute, sti.wSecond);
GetDlgItem(IDC_TIME)->SetWindowText(time);
CDialog::OnTimer(nIDEvent);
}
void CHSTATGLXTDlg::OnButtonInsertDatabase() {
CMyAdo m_wndAdo;
m_wndAdo.OnInitADOConn(CMyAdo::m_StrAccess);
CString temp;
temp=_T("select * from 在线主机信息");
m_wndAdo.pRecordset=m_wndAdo.OpenRecordset(temp);
for(int i=0;iAddNew();
m_wndAdo.pRecordset ->PutCollect("主机名称",(_bstr_t)Msg[i].Name);
m_wndAdo.pRecordset ->PutCollect("IP地址",(_bstr_t)Msg[i].Ip);
m_wndAdo.pRecordset ->PutCollect("MAC地址",(_bstr_t)Msg[i].Mac);
m_wndAdo.pRecordset ->PutCollect("在线时间",(_bstr_t)Msg[i].Onlinetime);
m_wndAdo.pRecordset ->Update();
}
m_wndAdo.CloseRecordset();
m_wndAdo.CloseConnection();
AfxMessageBox(_T("扫描数据已成功写入数据库!")); }
void CHSTATGLXTDlg::OnButtonSearch()
{
CSearchDialog m_wndSearch;
m_wndSearch.DoModal();
}
////////////////////////////////////////////////////////////////////////////////////////////SearchDialog.cpp
#include "stdafx.h"
#include "HSTAT GLXT.h"
#include "SearchDialog.h"
#ifndef MY_ADO
#include"MyAdo.h"
void CSearchDialog::OnButtonSearch()
{
UpdateData(true);
CMyAdo m_wndAdo;
CString SQL;
if(FALSE==m_wndAdo.OnInitADOConn(CMyAdo::m_StrAccess))
{
AfxMessageBox(_T("连接数据库失败!\n"));
return;
}
SQL.Format ( "SELECT * FROM 在线主机信息 WHERE MAC地址='%s'",
m_MacSearch );
m_wndAdo.pRecordset =m_wndAdo.OpenRecordset (SQL);
//m_wndAdo.ExcuteSQL(CString(_T("delete from 在线主机信息")));
if(m_wndAdo.pRecordset ->adoEOF||m_wndAdo.pRecordset ->adoBOF)
{
AfxMessageBox(_T("您所查询的数据不存在!\n"));
return;
}
int nCount=0;
CString temp;
_variant_t XuHao,ZhuJi,MAC,IP,Time;
while(!m_wndAdo.pRecordset ->adoEOF)
{
XuHao=m_wndAdo.pRecordset ->GetCollect(_T("序号"));
ZhuJi=m_wndAdo.pRecordset ->GetCollect(_T("主机名称"));
MAC=m_wndAdo.pRecordset ->GetCollect(_T("MAC地址"));
IP=m_wndAdo.pRecordset->GetCollect(_T("IP地址"));
Time=m_wndAdo.pRecordset->GetCollect(_T("在线时间"));
temp.Format ("%ld",(long)XuHao);
m_List.InsertItem(nCount,temp);
m_List.SetItemText(nCount,1,(LPCTSTR)(_bstr_t)ZhuJi);
m_List.SetItemText(nCount,2,(LPCTSTR)(_bstr_t)IP);
m_List.SetItemText(nCount,3,(LPCTSTR)(_bstr_t)MAC);
m_List.SetItemText(nCount,4,(LPCTSTR)(_bstr_t)Time);
nCount++;
m_wndAdo.pRecordset ->MoveNext ();
}
m_wndAdo.CloseRecordset();
m_wndAdo.CloseConnection ();
}
BOOL CSearchDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_List.InsertColumn(0,"序号",LVCFMT_LEFT,45);
m_List.InsertColumn(1,"主机名称",LVCFMT_LEFT,145);
m_List.InsertColumn(2,"IP 地址",LVCFMT_LEFT,118);
m_List.InsertColumn(3,"MAC地址",LVCFMT_LEFT,138);
m_List.InsertColumn(4,"在线时间",LVCFMT_LEFT,147);
return TRUE;