您好,欢迎访问三七文档
当前位置:首页 > 金融/证券 > 金融资料 > r语言与统计分析第五章课后答案
WLAN定位中的数据采集软件设计与实现摘要:本文从获取室内定位必要信息的角度,设计与实现了一种基于NDIS的无线网络信号扫描程序,并给出了其关键技术细节和设计框架。它由网络适配器搜索模块和无线网络扫描模块组成。该程序适用于WINDOWS平台下所有802.11X系列网络适配器。KEYWORDS:WLANNDIS扫描Abstract:ToacquiretheinformationusedinWLANLocating,thispaperspecifysthedesignandimplementationofaWLANsignalscansoftware,andthekeytechnologiesanddesignframehavebeenintroducedindetail.ThesoftwareincludetheNetworkDeviceslistingmoduleandtheWLANsignalscanmodule.Thedevelopedsoftworecanbeusedbyalltypesof802.11Xseriesnetworkdevices.1.前言近年来,随着近距离无线电技术的高速发展和无线局域网技术的进步,使得室内定位技术突飞猛进。基于IEEE802.11标准的室内环境的WLAN,通过测量来自接入点AP(AccessPoint)的信号强度RSS(ReceivedSignalStrength)或信噪比SNR(SignalNoiseRatio),或者通过测量来自MS(MobileStation)的RSS或SNR,来得到位置信息,进而提供定位和导航的综合功能。在定位过程中需要根据接收到的信号强度RSS来建立offline阶段的Radio-map,接着才能根据建立出的网络模型,采用传统的K近邻定位算法或者新提出的建立模糊推断系统,利用智能人工神经网络等技术在online阶段进行定位。可见,建立可靠的Radio-map是室内定位技术的基础,这需要使用无线网卡在一系列参考点上接收来自多个AP的无线信号并采集所需的信息。而NDIS(NetworkDriverInterfaceSpecification)是Windows下的网络驱动程序接口规范,只要按照NDIS规范,就不用考虑操作系统的内核以及与其他驱动程序的接口问题,这为开发无线网卡操作程序提供了强大的支持。本文主要研究了在WINDOWS操作系统以及VisualStudio2005开发环境下通过NDIS对网络适配器进行访问,获取来自局域网内的AP的信息,完成了WLAN定位中的数据采集软件的实现。2.关键技术介绍2.1NDISNDIS(NetworkDriverInterfaceSpecification)是Microsoft和3Com公司开发的网络驱动程序接口规范的简称。它为Windows下的网络驱动程序的开发带来许多方便。编写符合NDIS规范的驱动程序时,只要调用NDIS函数,而不用考虑操作系统的内核以及与其他驱动程序的接口问题,为操作系统对不同网络的支持提供了方便。NDIS定义了网卡或网卡驱动程序与上层协议驱动程序之间的通信接口规范,它屏蔽了底层物理硬件的不同,使上层的协议驱动程序可以和底层任何型号的网卡通信。NDIS支持三种类型的网络驱动程序:网卡驱动程序(NICdriver)、中间驱动程序(Intermediateprotocoldriver)和协议驱动程序(Upperlevelprotocoldriver)。NDIS是一个函数库,它为编写符合NDIS规范的驱动程序提供了编程环境。在这个环境中,各层驱动程序之间的通信全部由NDIS提供的统一的例程和调用来实现。它负责上下层驱动程序之间、服务原语和实际驱动程序入口之间的转换。NDIS定义了一组经过抽象的系统调用,用来屏蔽与操作系统或硬件相关的操作,例如内存管理、IO操作、系统资源同步等。这样使得基于NDIS开发的驱动程序与开发平台无关,增强了源代码的可移植性。2.2网络适配器搜索模块每当程序需要开始进行网络接入时,必须先搜索出所有可用的网络适配器,再根据用户的选择来激活指定的设备。网络适配器搜索模块完成搜索列表并将其存储在一个内部链表里,并为无线网络信号扫描模块提供所需要使用的设备句柄。在程序中,作者定义了一个CtrlFunc类,这个类包括了完成网络适配器搜索以及无线信号的扫描的主要功能。类中定义了下列数据成员和函数:+CtrlFunc()+ClearNICList()+WLANDetect():NDIS_802_11_BSSID_LIST*+ActivateNIC(indevice_name:char*):bool+ShowNICList():BOOL+OpenRegKey():NICinfo*+~CtrlFunc()-Reg_to_NICinfo(indesc:char*,inname:char*)-DeleteNIC()-Save_NIC_info(inIndex:int,inkey_name:char*,indevice_info:char*,indevice_description:char*):BOOLCtrlFunc-NIC_handle:HANDLE-NIC_devices:NICinfo*-NIC_pBSSIDList:NDIS_802_11_BSSID_LIST*图1CtrlFunc类的结构图CtrlFunc类的私有数据成员:NIC_handle:定义为设备句柄;NIC_devices:定义为一个NICinfo类型结构体;CtrlFunc类的公共成员函数:ClearNICList():定义此函数,来清除当前读入的设备信息。ActivateNIC():定义此函数来激活当前用户选择的网络适配器,并把设备句柄传递给NIC_handle。ShowNICList():定义此函数访问注册表网络适配器子键,并不断调用Save_NIC_info函数读值,在每次读值后调用Reg_to_NICinfo把值存入一个内部链表NICinfo里。OpenRegKey():定义此内联函数用于传值。CtrlFunc类的私有成员函数:Reg_to_NICinfo():定义此函数来把从注册表中读出的值存进一个内部链表里。DeleteNIC():定义此函数Save_NIC_info():定义此函数将注册表中的网络适配器的注册表中的子键name和description键值读入参数device_info和device_description中。在网络适配器搜索模块内部——首先,程序控制设备时必须要使程序获取该设备的句柄。我们使用ShowNICList函数来读取所有的设备硬件信息,并将其存储在一个对用户不可见的内部链表中。在WINDOWS环境下,所有网络适配器的注册表子键位置为SOFTWARE\\Microsoft\\WindowsNT\\CurrentVersion\\NetworkCards。ShowNICList函数将调用RegOpenKeyExA和RegEnumKeyExA函数访问本机注册表,打开注册表下的NetworkCards子键,然后调用Save_NIC_info函数读取设备的属性信息。Save_NIC_info函数将调用RegQueryValueEx函数读入注册表的name和description键值,并同时赋值给形参device_info和device_description。然后,ShowNICList函数调用Reg_to_NICinfo函数将其存进内部链表,作为一个单独的内部链表结点,接着指针将指向下一个设备。当遍历完所有设备后,程序将释放注册表键的句柄,并查询内部链表是否为空。如果内部链表不为空,用户可见的外部链表将会把用户指定的设备名称传递给内部链表,然后程序将使用ActivateNIC函数调用CreatFileA函数来完成设备的激活,并将设备的句柄保存在NIC_handle中提供给无线网络信号扫描模块使用。在整个模块中,一旦出现访问注册表失败,内部链表为空和无法打开设备时,系统将会报错,并退出应用程序。开始获得子键句柄调用save_NIC_info获得设备属性信息遍历所有设备释放指定注册键的句柄获得设备列表为空选择网络适配器打开网卡成功成功激活并返回报错退出应用程序是是是是否否否图2无线网络适配器搜索模块流程图2.3无线网络信号扫描模块当网络适配器搜索模块完成搜索并确定用户所选择的设备句柄,将其保存在NIC_handle中后,无线网络信号扫描模块将使用这个句柄操作设备,并完成无线网络信号的搜索。CtrlFunc类的私有数据成员:NIC_pAlloc:动态分配内存的首地址。CtrlFunc类的公共成员函数:WLANDetect():通过内部的Win32API函数的DeviceIoControl来完成对无线网络适配器的操作,从网卡中读出无线局域网中各个AP的信号信息,并返回AP的数量和每个AP的MAC地址。CtrlFunc类的私有成员函数:DeleteNIC():清除内部链表NIC_devices的值,释放设备句柄。头文件ntddndis.h:定义了使用网络驱动接口设备所需的所有参数和数据类型。其中结构体NDIS_802_11_BSSID_LIST内存储了每个AP的信息包和无线网络中的AP数量;在结构体NDIS_WLAN_BSSID内存储了某一个AP信息包,其中包括了BSSID、SSID、RSS和Encryption等信息。在无线网络信号扫描模块中,首先调用的函数是WLANDetect,它先清除网络适配器信息,之后通过VirtualAlloc为结构体NDIS_802_11_BSSID_LIST动态分配足够长度的内存空间,动态分配的空间首地址指针为NIC_pBSSIDList。然后在搜索到设备的情况下,使用DeviceIoControl函数和网络适配器搜索模块传来的NIC_handle设备句柄来对所选中的适配器来进行操作,具体的操作为向选定的网络适配器发送操作码IOCTL_NDIS_QUERY_GLOBAL_STATS,来分别完成对网卡的参数设置和查询,在对网卡进行参数设置时,输入缓存区地址为OID_802_11_BSSID_LIST_SCAN;查询网卡信息时,输入缓存区地址为OID_802_11_BSSID_LIST。如果发现网卡上缓存了一个数据包需要接收,则通知已动态分配的内存空间作为输出缓冲区来使程序读入无线网卡返回的信息,在NIC_pAlloc指向的内存空间内存储了AP的数量和第一个AP的信息包结构体首地址,此信息包以NDIS_802_11_BSSID结构体形式存在。AP1AP2APn结构体APi为NDIS_802_11_BSSIDBSSID[1]cpSsid结构体NDIS_802_11_BSSID_LISTMacAddressLengthSsidMacAddressLengthSsidMacAddressLengthSsid动态分配物理空间图3内存空间分配过程在得到了上述信息后,程序创建一个指向_NDIS_802_11_BSSID_LIST类型结构体的指针WLANBSSIDList,取出BSSID[1],即第一个AP信息包的首地址指针值传递给一个指向_NDIS_802_11_BSSID结构体的指针pSSidAdr。接着,通过pSSidAdr将结构体中的信息依次取出。当已经取出当前结构体的所有信息后,程序将pSSidAdr指向的内存位置加上整一个_NDIS_802_11_BSSID结构体的长度,以此指向下一个结构体的入口位置。遍历所有结构体,即扫描到的所有AP的信息包后,程序已经获得了本次扫描到的无线网络信号的完全信息。由于程控网卡需要一定的时间来做出响应,因此,程序将线程阻塞一定时间后,再次调用WLANDetect函数来开始无线网络扫描过程,以获取AP信息的更新。需注意的是,这里应使用一个WHILE(TRUE)判断语句来确保程序每次扫描时都会重新分配足够的内存空间。开始对网卡进行参数设置查询网卡
本文标题:r语言与统计分析第五章课后答案
链接地址:https://www.777doc.com/doc-2856600 .html