目录
- 引言 4
1.1. 文档目的 4 1.2. 参考文献 4 1.3. 符号和缩略语 4 - 总体设计介绍 4
2.1. 概述 4 2.2. 功能定义 5 2.2.1. WIFI驱动功能定义 5 2.2.2. WIFI安全定义 6 2.3. 系统资源需求与依赖 7 2.3.1. 硬件资源框图 7 2.3.2. 软件资源 8 2.4. 软件设计方案 8 2.4.1. WIFI驱动框架结构 8 2.4.2. LIBWIFI模块驱动软件方框图 10 2.4.2.1. 无线网卡控制模块 11 2.4.2.2. 机型仓库 11 2.4.2.3. wap_supplicant模块 11 2.4.2.4. 接口模块 15 2.4.2.5. IPC通信模块 15 2.4.2.6. WIFI主控模块 15 - 设计要点 20
- 可靠性设计 21
4.1. 概述 21 4.2. 可靠性分析与验证 21 4.2.1. TCP/IP通信可靠性 21 4.2.2. WIFI驱动程序健壮度 22 - 附录 22
- 引言
1.1. 文档目的 本文档的目的在于提供开发团队一个WIFI通信底层的架构体系,使团队的成员把开发重点更多地移到对业务逻辑的开发和用户体验上,而无需考虑其他(如底层WIFI热点、连接过程等)底层的操作上。从而进一步规范代码的编写和提升代码的质量。使被开发的系统更容易维护和重用。 有什么好的建议的话,敬请提出。 1.2. 参考文献 【1】 无线WiFi以及WLAN技术基础知识介绍,2014年5月 【2】 802.11无线网络权威指南(第二版),华为3COM,2006年8月 1.3. 符号和缩略语 缩写、术语 解 释 WIFI (Wireless Fidelity)无线保真。 STA Station的简写,表示连接到无线网络中的设备,这些设备通过AP,可以和内部其它设备或者无线网络外部通信。 AP Access Point,是一个无线网络中的特殊节点,通过这个节点,无线网络中的其它类型节点可以和无线网络外部以及内部进行通信。 WLAN Wireless Local Area Network,无线局域网。 WEP Wired Equivalent Privacy,有线等效加密,是原始 IEEE 802.11 标准中的数据加密方法。 WPA Wi-Fi Protected Access (WPA)是基于IEEE 802.11i标准草稿的一个安全协议。 WPA2 Wi-Fi Protected Access II,是基于IEEE 802.11i正式标准的一个安全协议,是WPA的升级版,比WPA更安全。 PSK 预共享密钥是用于验证 L2TP/IPSec 连接的 Unicode 字符串。
SSID Service Set Identifier的缩写,服务集标识。用来标识一个无线网络。 BSSID 用来标识一个BSS,其格式和MAC地址一样,是48位的地址格式。一般来说,它就是所处的无线接入点的MAC地址。
- 总体设计介绍
2.1. 概述 由于传统的以太网需要在现场进行布线,而有些客户不愿意在进行布线,而希望通过wifi热点的方式来访问internet。新机器都开始要求具备支持wifi连接的能力。在硬件上,目前是通过USB或SDIO接口外接一个无线网卡(支持802.11协议),从而实现WIFI接入internet的功能。在软件上,包括无线网卡的USB驱动或无线网卡SDIIO驱动、无线网卡中间接口层和上层WIFI界面管理程序等几个部分。USB、SDIO接口在机器上都已经普遍支持,而无线网卡的USB驱动或SDIO驱动都是由模块厂商直接提供。因此,软件上的工作主要是实现无线网卡中间接口层和上层的界面管理程序。 在WIFI交易过程中,终端跟后台之间也是通过internet进行连接。首先,交易数据经过终端一侧的无线网卡发送到AP,AP再发送到网关后,将TCP/IP数据包传送到internet,再通过internet网络和后台交互数据。 上图就是简单的WIFI通信网络,其需要通过两个步骤连接后台:
- 终端需要先通过指定的SSID和密码连接到指定的AP中,实现终端接入internet的能力。
- 终端通过internet实现和后台之间的交互数据。
2.2. 功能定义 2.2.1. WIFI驱动功能定义 (注:以《 WIFI驱动软件标准规范》的功能需求章节为准)。 序号 支持的功能 功能要求 备注 1 WIFI开启 & 关闭 1) WIFI开启 2) WIFI关闭 2 无线网卡信息获取 1) 获取无线网卡信息 ① 网卡描述符; ② 网卡MAC ③ 网卡状态; 3 连接热点信息设置 1) 设定需要连接热点的相关信息 ① SSID ② 加密机制 ③ 密码 4 热点扫描 1) 查询当前可扫描到的热点SSID列表 2) 查询当前可扫描到的热点的信号强度值 ① SSID ② BSSID ③ 信号强度 ④ 加密机制(包括:1、Wi-Fi认证时使用的密钥管理协议;2、WPA认证时使用的广播密码加密方式;3、WPA认证协议使用的单播密码加密方式) 5 热点连接 1) 热点连接 6 热点断开 1) 断开已连接的SSID热点 7 连接状态查询 1) 当前热点的连接状态查询 8 当前网络信息获取 1) 获取当前网络信息 ① 本地IP; ② 本地网关; ③ 子网掩码; ④ 默认DNS; ⑤ 备份DNS; 9 当前网络信息设置 1) 设置当前网络信息 ① 本地IP; ② 本地网关; ③ 子网掩码; ④ 默认DNS; ⑤ 备份DNS; 功能定义提供了WIFI驱动能提供的全部功能,而对外则提供对应的接口来实现,接口请查看对应的接口文档。 2.2.2. WIFI安全定义 本章节定义WIFI安全需要的WIFI认证方式和加密方式 加密方案 认证方式 加密方式 备注 WEP 开放系统认证 无 不需要输入密码 共享密钥认证 ① WEP40(64位) ② WEP104(128位) ③ WEP152(152位) ① 64位加密方式+16进制的密钥格式 = 10个数字字符组成的密码; ② 64位加密方式+ASCII码的密钥格式 = 5个ASCII码字符组成的密码; ③ 128位加密方式+16进制的密钥格式 = 26个数字字符组成的密码; ④ 128位加密方式+ASCII码的密钥格式 = 13个ASCII码字符组成的密码; ⑤ 152位加密方式+16进制的密钥格式 = 32个数字字符组成的密码; ⑥ 152位加密方式+ASCII码的密钥格式 = 16个ASCII码字符组成的密码. WPA 1) WPA 2) WPA-PSK 3) WPA2 4) WPA2-PSK ① AES(AES-CCMP) ② TKIP ① WPA-PSK只能使用TKIP这种加密方式。 ② WPA-PSK(预先共享密钥Wi-Fi保护访问)或WPA2-PSK是WPA或WPA2的简化版。 ③ WPA和WPA-PSK、WPA2和WPA2-PSK采用了相同的加密机制,其区别仅在于WPA-PSK、WPA2-PSK的认证机制只有简单的一般密码,而不是针对用户特定的账户属性进行身份认证。 ④ AES和TKIP这二种加密方式对密钥的要求的话都是8-63个字符。 WAPI 1) WAPI PSK 2) WAPI 证书 暂不支持
2.3. 系统资源需求与依赖 2.3.1. 硬件资源框图 
- MCU:控制WIFI块的微控制器。
- USB:MCU与WIFI模块之间的通信方式之一。
- SDIO:MCU与WIFI模块之间的通信方式之一。
- 无线网卡:是终端无线网络的设备,是不通过有线连接,采用无线信号进行数据传输的终端。
2.3.2. 软件资源 依赖软件资源 解 释 wpa_supplicant wpa_supplicant is a WPA Supplicant for Linux, BSD, Mac OS X, and Windows with support for WPA and WPA2 (IEEE 802.11i / RSN). It is suitable for both desktop/laptop computers and embedded systems. Supplicant is the IEEE 802.1X/WPA component that is used in the client stations. It implements key negotiation with a WPA Authenticator and it controls the roaming and IEEE 802.11 authentication/association of the wlan driver. wpa_supplicant is designed to be a “daemon” program that runs in the background and acts as the backend component controlling the wireless connection. wpa_supplicant supports separate frontend programs and a text-based frontend (wpa_cli) and a GUI (wpa_gui) are included with wpa_supplicant. wpa_supplicant uses a flexible build configuration that can be used to select which features are included. This allows minimal code size (from ca. 50 kB binary for WPA/WPA2-Personal and 130 kB binary for WPA/WPA2-Enterprise without debugging code to 450 kB with most features and full debugging support; these example sizes are from a build for x86 target). 系统内Socket通信机制 提供与其他程序的通信接口 USB USB驱动 SDIO SDIO驱动
2.4. 软件设计方案 2.4.1. WIFI驱动框架结构 的驱动架构比较特殊,他需要用到开源软件 WIFI驱动模块是通过加载对应无线网卡的驱动,来实现无线网卡的初始化。此时在系统中会生成对应的无线网卡设备节点。后续驱动通过开源软件wap_supplicant来实现无线网络热点的扫描与连接。当连接上对应热点后,系统就可以通过对应无线网卡设备节点来实现标准的socket通信,下图示为WIFI驱动在系统中的架构示意图:
下图示为WIFI驱动在系统中的工作流程架构示意图: 
APP通过调用SDK来启动WIFI驱动线程,SDK通过WIFI驱动提供的对外接口(动态库)给WIFI控制线程发送各种交互消息来控制WIFI驱动。WIFI驱动根据SDK调用的接口控制WIFI模块的相应操作。当SDK控制WIFI驱动连接上某个有效热点后,无线网卡生成的对应设备节点可作为标准网卡使用,此时系统内的全部应用都可以通过此网卡,对外实现网络通信。 2.4.2. LIBWIFI模块驱动软件方框图 LIBWIFI驱动的软件分为两部分结构:WIFI主控流程和对外动态库。具体驱动软件方框图如下图所示: 
WIFI主控流程:为单独的动态库,由通信管理模块调用,其直接控制WIFI的主流程和负责wpa_supplicant交互。
2.4.2.1. 无线网卡控制模块 该模块主要实现不同无线网卡的识别(可通过配置文件读取)、对应驱动加载、无线网卡运行情况监控(如网卡被拔出等)。 2.4.2.2. 机型仓库 该模块主要根据机型提供对应设备节点的操作,如提供USB设备节点,SDIO设备节点和IO控制节点等信息。 2.4.2.3. wap_supplicant模块 该模块主要提供控制wap_supplicant进程启动、关闭和通信的接口。 2.4.2.3.1. 什么是wap_supplicant wpa_supplicant本是开源项目源码,被谷歌修改后加入android移动平台,它主要是用来支持WEP,WPA/WPA2和WAPI无线协议和加密认证的,而实际上的工作内容是通过socket(不管是wpa_supplicant与上层还是wpa_supplicant与驱动都采用socket通讯)与驱动交互上报数据给用户,而用户可以通过socket发送命令给wpa_supplicant调动驱动来对WiFi芯片操作。 简单的说,wpa_supplicant就是WiFi驱动和用户的中转站外加对协议和加密认证的支持。 wpa_supplicant所支持的功能非常多,此处列举其中几个重要的功能点。 支持WPA和IEEE 802.11i所定义的大部分功能:这部分功能集中在安全方面,包括: ? 支持WPA-PSK(即WPA-Personal)和WPA-Enterprise(即利用RAIDUS认证服务器来完成身份认证的情况)。 ? 数据加密方面支持CCMP、TKIP、WEP104和WEP40。注意,WEP104和WEP40中的数字代表密钥的长度。104表示密钥长度为104个二进制位(如以ASCII字符个数来计算的话,WEP104支持的密钥长度为13个ASCII字符)。 ? 完全支持WPA和WPA2,包括PMKSA缓存,预认证(pre-authentication)等功能。 ? 支持IEEE 802.11r和802.11w,其中802.11r规范定义了快速基础服务转移(Fast Transition)功能,而802.11w则新增了对管理帧的安全保护机制。 ? 支持WFA制定的Wi-Fi Proctected Setup功能、P2P、TDLS等。 支持多种EAP Method:主要和802.1X中Supplicant的功能有关,wpa_supplicant支持多达25种EAP Method,包括: ? EAP-TLS:TLS(Transport Layer Security)本身是一种传输层安全协议,它利用密钥算法提供端点身份认证与通讯保密,其基础是公钥基础设施(public key infrastructure,简称PKI)。EAP-TLS定义于RFC 5216。 ? EAP-PEAP:PEAP(Protected Extensible Authentication Protocol,可扩展EAP)由微软、思科以及RSA Security三个公司共同开发,是一种利用证书加用户名和密码来进行身份验证的方法。 ? EAP-TTLS:它是TLS的拓展,全名为Tunneled Transport Layer Security(隧道传输层安全协议),相比TLS,它简化了认证过程中客户端的工作。 ? EAP-SIM、EAP-PSK、EAP-GPSK等其他认证方法。 对各种无线网卡和驱动的支持: ? 支持nl80211/cfg80211驱动和Linux Wireless Extension驱动。 ? 支持Windows平台中的NDIS驱动。 2.4.2.3.2. wpa_supplicant架构介绍 wpa_supplicant是一个比较庞大的开源软件项目,包含500多个文件,20万行代码,其内部模块构成如下图所示: 
所示的wpa_supplicant软件架构包括如下重要模块: ? wpa_supplicant所有工作都围绕事件(对应图4-1中的event loop模块)展开。即,它是基于事件驱动的。事件驱动和消息驱动类似,主线程等待事件的发生并处理它们。WPAS没有使用多线程编程,所有事件处理都在主线程中完成。从这一点看,wpa_supplicant的运行机制倒是很简单。 ? 位于event loop模块下方的driver i/f(i/f代表interface)接口模块用于隔离和底层驱动直接交互的那些driver控制模块(如wext、ndiswrapper等,wpa_supplicant中称之为driver wrapper)。这些driver wrapper和平台以及芯片所使用的驱动相关。不过,由于driver i/f的隔离作用,WPAS中其他模块将能最大程度保持平台以及驱动无关性。 ? driver wrapper经常要返回一些信息给上层。wpa_supplicant中,这些信息将通过driver events的方式反馈给wpa_supplicant其他模块进行处理。 ? 上面介绍曾介绍过EAP以及EAPOL协议。除了定义消息格式外,RFC4137文档定义了EAP状态机,而802.1X文档中还定义了EAPOL状态机。WPAS根据这两个协议分别实现了EAP和EAPOL状态机。本章后续将详细分析这两个状态机以及背后的协议。除此之外,WPAS还定义了自己的状态机(即WPA/WPA2 State Machine)。 ? wpa_supplicant实现了多种EAP方法,如上图中EAP method模块所示。另外它还包含了TLS模块和crypto模块用于支持对应的EAP方法。 ? EAPOL以及EAP消息都属于LLC层数据,所以wpa_supplicant的l2_packet模块用于收发EAPOL和EAP消息。 ? wpa_supplicant支持较多的配置参数,这些参数的处理由configuration模块完成。 ? wpa_supplicant是C/S结构中的Server端,它通过ctrl i/f模块向客户端提供通信接口。Linux/Unix平台中,Client端利用Unix域socket与其通信。目前常用的Client端wpa_cli(无界面的命令行程序)和wpa_gui(UI用Qt实现)。 2.4.2.3.3. wpa_supplicant配置介绍 wpa_supplicant支持众多功能,使用前往往需根据平台或驱动的特性进行编译配置,其源码包已经提供了一个默认配置文件,路径为/wpa_supplicant/wpa_supplicant/defconfig,编译wpa前需要把该配置文件拷贝为/wpa_supplicant/wpa_supplicant/.config,并修改提对应配置,下面会介绍几个主要的配置参数 宏名字 宏说明 
2.4.2.3.4. wpa_supplicant命令介绍 由wpa架构图,wpa对外通过控制接口模块与客户端通信。在NOS平台中,wpa的客户端是libwifi.so。用户在Settings界面进行Wi-Fi相关的操作最终都会经由libwifi.so通过发送命令的方式转交给wpa_supplicant去执行。wpa定义了许多命令,常见的:
PING:心跳检测命令。客户端用它判断WPAS是否工作正常。WPAS收到”PING”命令后需要回复“PONG”。 MIB:客户端用该命令获取设备的MIB信息。 STATUS:客户端用该命令来获取WPAS的工作状态。 ADD_NETWORK:为WPAS添加一个新的无线网络。它将返回此新无线网络的id(从0开始)。注意:此network id非常重要,客户端后续将通过它来指明自己想操作的无线网络。 SET_NETWORK :network id是无线网络的id。此命令用于设置指定无线网络的信息。其中variable为参数名,value为参数的值。 ENABLE_NETWORK :使能某个无线网络。此命令最终将促使WPAS发起一系列操作以加入该无线网络。 除了接收来自Client的命令外,wpa也会主动给Client发送命令。例如,wpa需用户为某个无线网络输入密码。这类命令称之为Interactive Request,其格式如下。
wpa向客户端发送的命令遵循CTRL-REQ---格式。如CTRL-REQ-PASSWORD-0-Passwork needed for SSID test-network。这条命令表示需要用户为0号网络输入密码。 客户端处理完后,需回复CTRL-RSP---。目前支持的field包括PASSWORD、IDENTITY(EAP中的identity或者用户名)、PIN等。 最后,wpa还可通过形如“CTRL-EVENT--
”的命令向客户端通知一些事情。
提示:除了“CTRL-EVENT-XXX”之外,WPAS还支持形如“WPA:XXX”和“WPS-XXX”的通知事件。这些事件和WPA和WPS有关。下一章分析WifiService时我们还能见到它们。
上图所示为利用wpa_cli测试status命令得到的结果。 2.4.2.3.5. wpa_supplicant控制API介绍 客户端使用wpa_ctrl时首先要分配控制对象。下面两个API用于创建和销毁控制对象wpa_ctrl: 
下面这个函数用于发送命令给wpa。  msg_cb是一个回调函数,该参数的设置和wpa中C/S通信机制的设计有关: 从Client角度来看,它发送给wpa的命令所对应的回复属于solicited event(意为有请求的事件),而前面所提到的CTRL-EVENT事件(用于通知事件)对应为unsolicited event(意为未请求的事件)。当Client在等待某个命令的回复时,wpa同时可能有些通知事件要发送给客户端,这些通知事件不是该命令的回复,所以不能通过wpa_ctrl_request的reply参数返回。
为了防止丢失这些通知事件,wpa_cli设计了一个msg_cb回调用于客户端在等待命令回复的时候处理那些unsolicited event。 这种一个函数完成两样完全不同的功能的设计实在有些特别,所以wpa_supplicant规定只有打开通知事件监听功能的wpa_ctrl对象才能在wpa_ctrl_request中通过msg_cb获取通知事件。而打开通知事件监听功能相关的API如下所示。 
如果客户端并不发送命令,而只是想接收Unsolicited event的话,可通过wpa_ctrl_recv函数来达到此目的。 综上所述,单独使用wpa_ctrl_recv和wpa_ctrl_request都不方便。所以,一种常见的用法是:客户端创建两个wpa_ctrl对象来简化自己的逻辑处理: ? 一个打开了通知事件监听功能的wpa_ctrl对象将只通过wpa_ctrl_recv来接收通知事件。 ? 另外一个wpa_ctrl专职用于发送命令和接收回复。由于没有调用wpa_ctrl_attach,故它不会收到通知事件。 2.4.2.4. 接口模块 该模块主要实现定义的对外接口函数,代码需要严格按照接口标准来实现。 2.4.2.5. 通信模块 实现进程间的通信,由so库提供对应的通信接口,本模块负责该接口的封装。 2.4.2.6. WIFI主控模块 该模块为整个WIFI驱动程序的中心,所有功能都依赖于本模块来调度。实现WIFI进程的工作流程、控制各个模块之间的相互协调。 WIFI主控模块主要依赖eloop多路复用监听多个事件框架来实现异步事件处理。以下分别介绍主架构和eloop框架的内容。 2.4.2.6.1. 主控模块架构 下图为主控模块流程框图: 
WIFI模块主要通过接口来触发。
WIFI主控模块初始化时靠执行wifi_init()接口(由通信管理程序执行)来触发,libwifi.so会执行如下步骤: ? 初始化系统参数。 ? 获取平台和模块参数。 ? 根据平台和模块参数,加载无线网卡驱动。 ? 生成wpa_supplicant配置文件。 ? 启动wpa_supplicant进程。 ? 初始化eloop处理框架。 ? 注册对应需要执行的eloop事件回调函数。 ? 执行eloop_run()循环,处理异步事件。 当wpa_supplicant进程运行后,会通过wext接口控制无线网卡。此时在eloop初始化时注册的timeout回调函数会让libwifi和wpa_supplicant之间建立起一条内部socket通信,并生成一条与wpa_supplicant的通信句柄,并实时维护此通信的句柄,当该通信句柄断开后马上执行重连。 而应用执行其他接口,则都是通过此通信句柄来控制wpa_supplicant实现的,具体包含如下命令: ? “SCAN”:扫描热点。 ? “SCAN_RESULTS”:获取热点扫描结果。 ? “STATUS”:获取wpa_supplicant当前状态。 ? “LIST_NETWORKS”:列出连接网络状态和参数。 ? “REMOVE_NETWORK”:删除已有的网络连接。 ? “ADD_NETWORK”:增加新的网络连接。 ? “SET_NETWORK”:设置网络连接的对应参数,如ssid、psk等参数。 ? “SAVE_CONFIG”:保存网络设置参数。 ? “SELECT_NETWORK”:选择指定的网络连接。 ? “ENABLE_NETWORK”:使能指定的网络连接,让wpa_supplicant去连接该热点。 ? “DISCONNECT”:断开已连接的热点。 ? “SIGNAL_POLL”:获取已连接网络热点的信号强度。 ? “RECONNECT”:重连已有的网络热点。 当应用执行wifi_close ()接口时,libwifi.so会执行如下步骤: ? 发送信号给eloop框架,使退出eloop_run(),并释放对应的资源。 ? 发送断开热点连接。 ? 关闭wpa_supplicant进程。 ? 关闭dhcp进程。 ? 关闭无线网卡,并卸载对应驱动。 ? 退出WIFI主控线程,释放对应资源。 2.4.2.6.2. eloop框架
- 重要结构体定义
struct eloop_sock { int sock; void *eloop_data; void *user_data; eloop_sock_handler handler; //该handler是一个方法,后续socket有变化,就会调用相应的socket所在的结构体中的handler方法来处理 WPA_TRACE_REF(eloop); WPA_TRACE_REF(user); WPA_TRACE_INFO };
struct eloop_timeout { struct dl_list list; //双向链表 struct os_time time; void *eloop_data; void *user_data; eloop_timeout_handler handler; WPA_TRACE_REF(eloop); WPA_TRACE_REF(user); WPA_TRACE_INFO };
struct eloop_signal { int sig; void *user_data; eloop_signal_handler handler; int signaled; };
struct eloop_sock_table { int count; struct eloop_sock *table; //eloop_sock类型的变量 int changed; };
struct eloop_data { int max_sock;
int count; /* sum of all table counts */
struct eloop_sock_table readers;
struct eloop_sock_table writers;
struct eloop_sock_table exceptions;
struct dl_list timeout;
int signal_count;
struct eloop_signal *signals;
int signaled;
int pending_terminate;
int terminate;
int reader_table_changed;
};
以下列出这些结构体的关系图:  struct eloop_data结构体是一个统领全局的数据结构,只有一个实例: //创建了一个静态全局变量,类型为eloop_data static struct eloop_data eloop; 这个变量会处理三大类型的Event事件:
- socket事件
- timeout事件
- signal事件
socket事件还分为三个类型: ? EVENT_TYPE_READ:Socket有数据刻度 ? EVENT_TYPE_WRITE:Socket有新数据可写 ? EVENT_TYPE_EXCEPTION:Socket有异常事件发生 定义eloop_data结构体事件的处理: a) Socket事件:有readers,writers,exceptions三个eloop_sock_table结构体,每个里面都有一个eloop_sock类型的指针table,这里可以将该指针变量理解成动态数组。可以向各个table里面添加、删除eloop_sock。事件分发就是遍历eloop_sock_table,依次运行里面的每个handler。 b) Timeout事件:每个struct eloop_timeout都被放在一个双向链表中, 链表头就是eloop_data中的“timeout”项。这些struct eloop_timeout按超时先后排序。 c) Signal事件:每个struct eloop_signal都通过eloop_signal类型的指针链接起来。
- 基于Select的多Event处理
eloop_run方法中的“死循环”: while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) 如果eloop.terminate变为非零值,就会退出循环。这是为了提供一种从外部结束循环的方法。 如果eloop.terminate为零,只要timeout链表或者任一个Socket不为空,都会继续循环。
select系统调用的原型是: int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 在循环体里面:
- 找到timeout链表的第一项(因为是按超时先后排序的,所以第一项肯定是最先超时的),计算超时时间距现在还有多久,并据此设置select的timeout参数。
- 设置rfds,wfds和efds三个fd_set:方法是遍历各个eloop_sock_table,把每个sock描述符加入相应的fd_set里面。
- 调用select。可能阻塞在此处。
- eloop_process_pending_signals()处理Signal事件。
- 判断是否有超时发生,如果是则调用其handler,并从timeout链表移除。然后继续下次循环。
- 如果不是超时事件,则应该是rfds, wfds或者efds事件,fd_set里面会被改变,存放发生事件的描述符。因此分别遍历三个sock_table,如果其描述符在fd_set里面则调用其handler方法。
- 继续下次循环。
- 设计要点
- 无线网卡模块匹配:
目前使用多款无线网卡,并且以后会兼容市面上多款无线网卡,那么必须考虑需要多种无线网卡兼容的方案,目前USB和SDIO接口的无线网卡可以通过自动匹配获取,但是还是建议本平台使用配置文件的方式写死模块的型号。由于无线网卡接口种类繁多,那么对于USB接口的无线网卡,考虑到可能会使用外置无线网卡,建议可以写成USB接口,不写无线网卡的具体型号,该识别功能由软件自动识别。而对于SDIO接口的无线网卡,建议把对应接口类型和型号都写入到配置文件中,以便程序能快速识别。 - 无线网卡插拔监控:
无线网卡接口种类繁多,我们需要考虑外置USB接口的无线网卡,此种无线网卡容易在使用过程中被用户拔出,那么我们必须有一种机制来兼容无线网卡的连接状态。 - 路由信息选择:
当无线网卡接入后会获取IP信息,而若无线移动网络也同时在线,那么就会导致网络路由信息混乱,这个需要设定一个策略控制路由信息。目前比较成熟的策略是手机上的策略:只要WIFI在线,那么无线移动网络就自动断线,当WIFI关闭后,需要把无线移动网络设置为原来开启WIFI之前的状态。本功能需要有SDK或者应用来控制。底层不在负责本功能策略。 - USB接口无线网卡低功耗:
需要对USB接口的无线网卡低功耗进行验证,判断该功能是否稳定。
- 可靠性设计
4.1. 概述 WIFI通信的可靠性基于三个部分:硬件的可靠性、软件的可靠性和线路稳定可靠。由于涉及范围,本文只讨论软件的可靠性设计。 对于WIFI通信的软件可靠性设计涉及到以下几个方面:
- 无线网卡接口稳定可靠性。
- TCP/IP通信可靠性。
- 程序健壮度。
4.2. 可靠性分析与验证 4.2.1. TCP/IP通信可靠性 TCP 协议是一种面向连接的,为不同主机进程间提供可靠数据传输的协议。TCP 协议假定其所使用的网络栈下层协议(如IP 协议)是非可靠的,其自身提供机制保证数据的可靠性传输。在目前的网络栈协议族中,在需要提供可靠性数据传输的应用中,TCP 协议是首选的,有时也是唯一的选择。TCP 协议是在最早由Cerf 和Kahn[1]所提出的有关网络数据包传输协议的概念之上建立的。TCP 协议被设计成符合分层协议结构,工作在ISO/OSI 七层网络模型中的传输层中,使用网络层协议(如最常见的IP 协议)提供的服务。网络层协议尽最大努力传输上层提供的数据但并不保证数据传输的可靠性。可靠性保证必须由上层协议(如TCP 协议)提供。
网络层协议主要完成的工作有:
- 实现不同网络(主机)间的数据包路由传递。
- 在发送端(或中转站)提供数据包分片功能以使数据包大小满足 PMTU(Path-MTU)。
- 在接收端提供数据包分片重组功能。
- 负责数据包优先级,安全性等问题。
传输层协议(主要针对 TCP 协议而言)主要完成的工作有(并非所有的传输层协议都需要提供这些功能如UDP 协议就不提供可靠性数据传输):
- 提供多路复用。
- 实现数据基本传输功能。
- 建立通信通道。
- 提供流量控制。
- 提供数据可靠性传输保证。
数据可靠性传输保证是其中最为重要的方面,也是TCP 协议区别于其它协议的最重要特性。所谓提供数据可靠性传输不仅仅指将数据成功的由本地主机传送到远端主机,数据可靠性传输包括如下内容:
- 能够处理数据传输过程中被破坏问题。
- 能够处理重复数据接收问题。
- 能够发现数据丢失以及对此进行有效解决。
- 能够处理接收端数据乱序到达问题。
TCP 协议声称可靠性数据传输,其底层实现机制主要包括三个方面:使用序列号对传输的数据进行编号,数据超时重传,数据确认应答。具体的可靠性的细节,可参考TCP/IP协议解析。 而为了测试TCP/IP通信的高可靠性,我们需要做以下测试验证,只有通过以下测试才能保证其通信的可靠性。 序号 测试方法 测试要求 备注 1 短时socket通信
- 连接指令热点(局域网)
- 建立socket
- 发送固定字节数据给后台
- 等待后台应答相同数据
- 断开socket
- 重复2~5 连续测试100000条通信,成功率保证在98%
2 长时socket通信 - 连接指令热点(局域网)
- 建立socket
- 发送固定字节数据给后台
- 等待后台应答相同数据
- 重复2~4
- 断开socket 连续测试100000条通信,成功率保证在98%
4.2.2. WIFI驱动程序健壮度 本测试可参考《WIFI驱动软件标准规范》中的可靠性要求章节。
- 附录
无
|