WIFI相关记录

     最近接到一个做wifi打印相关的需求,因此特地研究了下wifi相关知识。本文分为如下三个部分:

1.  wifi基本知识----相关概念

2.  组网相关知识

3. Linux下wifi驱动适配相关知识

4. wifi打印相关知识


一、wifi基本知识

1.WLAN的定义

      无线局域网(Wireless Local Area Network,即WLAN,无线局域网的缩写,指采用802.11无线技术进行互连的一组计算机和相关设备。也称为LAWN)是指以无线信道作传输媒介的计算机局域网,是有线联网方式的重要补充和延伸,并逐渐成为计算机网络中一个至关重要的组成部分,广泛适用于需要可移动数据处理或无法进行物理传输介质布线的领域。随着IEEE802.11无线网络标准的制定与发展,使无线网络技术更加成熟与完善。并已成功的广泛应用于众多行业,如金融证券、教育、大型企业、工矿港口、政府机关、酒店、机场、军队等。产品主要包括:无线接入点、无限网卡、无线路由器、无线网关、无线网桥等。

2. WI-FI(WIFI)的定义

      wifi的全称是Wireless Fidelity,又叫802.11b标准,是IEEE定义的一个无线网络通信的工业标准。该技术使用的使2.4GHz附近的频段,该频段目前尚属没用许可的无线频段(在2.4GHz及5GHz频段上免许可)。最高带宽为11 Mbps,在信号较弱或有干扰的情况下,带宽可调整为5.5Mbps、2Mbps和1Mbps;其主要特性为:速度快,可靠性高,在开放性区域,通讯距离可达305米,在封闭性区域,通讯距离为76米到122米,方便与现有的有线以太网络整合,组网的成本更低。

3. WLAN和WI-FI(WIFI)的区别

      Wlan是无线网络的缩写,又叫做无线局域网。同理无线城域网叫做Wwan。WIFI是无线网络中的一个标准,比如说那些IEEE 802.11a、b、g之类的都属于WIFI这个标准。

4. 802.11标准和补存

    802.11       1997年IEEE无线局域网标准制定
    802.11b     2.4GHz,直序扩频 传输速率 1Mbps -11Mbps。
    802.11a     5GHz ,正交频分复用,传输速率6Mbps-54Mbps,
    802.11g     2.4GHz,兼容802.11b,传输速率到22Mbps。
    802.1x      基于端口的访问控制协议(Port based network access control protocol)
    802.11i     增强WIFI数据加密和认证(WPA,RSN)
    802.11e    QoS服务
    WAPI      国标GB15629.11-2003无线局域网鉴别与保密基础结构(WAI WPI)

       1990年IEEE 802标准化委员会成立IEEE 802.11无线局域网标准工作组。该标准定义物理层和媒体访问控制(MAC)规范。物理层定义了数据传输的信号特征和调制,工作在2.4000~2.4835GHz频段。IEEE 802.11是IEEE最初制定的一个无线局域网标准,主要用于难于布线的环境或移动环境中计算机的无线接入,由于传输速率最高只能达到2Mbps,所以,业务主要被用于数据的存取。
      1999年,IEEE 802.11a标准制定完成,该标准规定无线局域网工作频段在5.15~5.825GHz,数据传输速率达到54Mbps/72Mbps(Turbo), 传输距离控制在10~100米。802.11a采用正交频分复用(OFDM)的独特扩频技术;可提供25Mbps的无线ATM接口和10Mbps的以太网无线帧结构接口,以及TDD/TDMA的空中接口;支持语音、数据、图像业务;一个扇区可接入多个用户,每个用户可带多个用户终端。
      1999年9月IEEE 802.11b被正式批准,该标准规定无线局域网工作频段在2.4~2.4835GHz,数据传输速率达到11Mbps。该标准是对IEEE 802.11的一个补充,采用点对点模式和基本模式两种运作模式,在数据传输速率方面可以根据实际情况在11Mbps、5.5Mbps、2Mbps、1Mbps的不同速率间自动切换,而且在2Mbps、1Mbps速率时与802.11兼容。802.11b使用直接序列(Direct Sequence)DSSS作为协议。802.11b和工作在5GHz频率上的802.11a标准不兼容。由于价格低廉,802.11b产品已经被广泛地投入市场,并在许多实际工作场所运行。
      IEEE 802.11e标准对无线局域网MAC层协议提出改进,以支持多媒体传输,以支持所有无线局域网无线广播接口的服务质量保证QoS机制。 IEEE 802.11f,定义访问节点之间的通信,支持IEEE 802.11的接入点互操作协议(IAPP)。 IEEE 802.11h用于802.11a的频谱管理技术。
      IEEE的802.11g标准是对流行的802.11b(即Wi-Fi标准)的提速(速度从802.11b的11Mb/s提高到54Mb/s)。802.11g接入点支持802.11b和802.11g客户设备。同样,采用802.11g网卡的笔记本电脑也能访问现有的802.11b接入点和新的802.11g接入点。 不过,基于802.11g标准的产品目前还不多见。如果你需要高速度,已经推出的802.11a产品可以提供54Mb/s的最高速度。802.11a的主要缺点是不能和802.11b设备互操作,而且与802.11b相比,802.11a网卡贵50%,接入点贵35%。
      IEEE 802.11i标准是结合IEEE 802.1x中的用户端口身份验证和设备验证,对无线局域网 MAC层进行修改与整合,定义了严格的加密格式和鉴权机制,以改善无线局域网的安全性。IEEE 802.11i新修订标准主要包括两项内容:“Wi-Fi保护访问”(WPA)技术和“强健安全网络”。Wi-Fi联盟计划采用 802.11i标准作为WPA的第二个版本,并于2004年初开始实行。

802.11四种主要物理组件:
    工作站(Station)
        构建网络的主要目的是为了在工作站间传送数据。所谓工作站,是指配备无线网络接口的计算设备。
    接入点(Access Point)
        网络所使用的帧必须经过转换,方能被传递至其他不同类型的网络。具备无线至有线的桥接功能的设备称为接入点,接入点的功能不仅于此,但桥接最为重要。
    无线媒介(Wireless Medium)
        标准以无线媒介在工作站之间传递帧。其所定义的物理层不只是一种,802.11最初标准化了两种射频物理层以及一种红外线物理层。
    分布式系统(Distribution System)
        当几个接入点串联以覆盖较大区域时,彼此之间必须相互通信以掌握移动式工作站的行踪。分布式系统属于802.11的逻辑组件,负责将帧转送至目的地。

5. WIFI的总体拓扑结构



6. WIFI的应用

(1) 无线AP+LAN的应用                   私网
     无线办公环境,家庭,防止非内部人员进入网络
            a、MAC地址过滤        
            b、ip+用户名的锁定  AP+router
(2) 无线+LAN+internet的应用            专网
       VPN: 公司之间异地互连的专用网络
                                 基于internet的公司局域网
       网络电话: NetPhone, IpPhone           
                                 基于VPN全面实现语音通话
       网络视频:基于Iweb的视频会议监控
                                 基于internet的数据流的解决   
(3) 行业应用
         1)企业:ERP….
                                    Server + ERP软件 + AP +PDA +CFWLAN
         2)医院:查询系统 病例、药品、监控…..
                                    Server + 医用软件 + AP +PDA +CFWLAN
         3)超市:广播系统、监控系统:
                                    Server + 发布软件 + AP + WCard+机顶盒+TV
         4)交通:各个交通路口的监控    IP、VPN
                                    Server + 监控软件 + AP + IpCAMServer+CAM
         5)铁路、航空、电信:  IP、VPN
                                    售票系统的通信专用网络的票务
                                    Server + 监控软件 + AP + IpCAMServer+CAM+ IpPhone

二、组网相关知识

1.  WIFI连接模式

Wlan802_11IBSS:                 即 Ad-Hoc 模式, 通常用于模块和网络设备的直接连接;
Wlan802_11Infrastructure:   用于模块通过 AP 和其他网络设备组成星形结构的无线网络;

      根据网络是否存在 AP,无线局域网有两种结构: INFRASTRUCTURE 类型和 AD HOC 类型。
      INFRASTRUCTURE 型网络由若干个 STA 和一个 AP 组成, STA 之间通信通过 AP 转发, AP 连接到有线骨干网上。 AD HOC 型由多个 STA 组成,相互之间直接通信,不存在 AP。这种方式不需要访问有线网络中的资源,只在无线通信设备之间相互通信。

     无线网络的拓扑结构主要有:无中心的分布对等方式( AD HOC) 、有中心的集中控制方式( INFRASTRUCTURE) 、以及上述方式的混合方式。

     在分布式对等方式下,无线网中的任意两站之间可以直接通信,无需设中心转接站。这时, MAC 控制功能由各站分布管理。 这种方式同 IEEE802.3 局域网类似,网上的站共享一个无线通道,通常使用 CSMA/CA 作为 MAC 协议。这种方式的特点是结构简单易维护。 由于采用分布控制方式,某一站的故障不会影响整个网络的运行。

     在集中控制方式情况下,无线网中设置一个中心控制站,主要完成 MAC 控制及信道的分配等功能。 网中的其它站在该中心的协调下与其它各站通信。由于对信道资源分配、 MAC 控制采用集中控制的方式,这样使信道利用率大大提高, 网络的吞吐性能优于分布式对等方式。当然引入中心站也使得无线网的结构复杂。但目前的无线产品都把这些复杂的功能作成透明的, 无需用户干预。

2. SSID
      加入 WiFi 网络的网络名称,长度应小于 32 个字节。

3. WEP KEY
     加入 WiFi 网络的 WEP 密钥, WEP 密钥的长度可以分为 5 字节或 13 字节,其他长度不接受, 可以输入ASICII 值或者 16 进制数,这个可以在 HEX 选项中设置。如 5 字节的 ASICII 值: EM380, 或者 16 进制数: 454D333830 产生的密钥是一样的。

4. 网络通信协议

     分别是 TCP 和 UDP。
     模块处于 TCP 模式时,通讯双方需按照主从模式建立数据传输通道之后,才能进行数据交换。
     模块处于 UDP 模式时,通讯双方只需要向对方地址发送数据即可,不需要建立传输链路。


     面向连接的 TCP:
     “面向连接” 就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了、对方拿起话筒才能相互通话。 TCP( TRANSMISSION CONTROL PROTOCOL,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个 TCP 连接必须要经过三次“对话” 才能建立起来,其中的过程非常复杂,我们这里只做简单、形象的介绍, 你只要做到能够理解这个过程即可。我们来看看 TCP 三次对话的简单过程:主机 A 向主机 B 发出连接请求数据包: “我想给你发数据,可以吗? ” ,这是第一次对话;主机 B 向主机 A 发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包: “ 可以,你什么时候发? ” ,这是第二次对话;主机 A 再发出一个数据包确认主机 B 的要求同步:“我现在就发,你接着吧! ” , 这是第三次对话。三次“ 对话” 的目的是使数据包的发送和接收同步,经过三次“ 对话” 之后,主机 A 才向主机 B 正式发送数据。TCP 协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他
计算机,对可靠性要求高的数据通信系统往往使用 TCP 协议传输数据。 

     面向非连接的 UDP 协议:
    “面向非连接” 就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。这与现在风行的手机短信非常相似:你在发短信的时候,只需要输入对方手机号就 OK 了。 不与对方建立连接,而是直接就把数据包发送过去! UDP 适用于一次只传送少量数据、对可靠性要求不高的应用环境。比如,我们经常使用“ping” 命令然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。例如,在默认状态下,一次“ping” 操作发送 4 个数据包。大家可以看到,发送的数据包数量是 4 包,收到的也是4 包(因为对方主机收到后会发回一个确认收到的数据包)。这充分说明了 UDP 协议是面向非连接的协议,没有建立连接的过程。正因为 UDP 协议没有连接的过程,所以它的通信效果高;但也正因为如此,它的可靠性不如 TCP 协议高。 QQ 就使用 UDP 发消息,因此有时会出现收不到消息的情况。

                                                                                                                  tcp 协议和 udp 协议差别


5. TCP/IP 协议栈部分

(1)IP 地址

      模块的本地 IP 地址。如果使用 DHCP, 模块的 IP 地址可以自动获得。当模块处于 TCP 服务器模式下,其他客户端网络设备就需要访问该地址来建立 TCP 连接。因此在TCP服务器模式下时, 不应该使用 DHCP 功能,以防止服务器地址的变化。 在配置软件中, TCP 服务器是不允许使用 DHCP 功能的。


(2)子网掩码

      注意和需要通讯的网络设备的掩码保持一致。

(3)网关地址

     模块需要访问 Internet 上的 IP 地址时,数据包需要通过局域网的网关发送到远端 IP,因此必须正确设置网关地址,一般来讲网关地址就是路由器的 IP 地址,或者是 AP 的 IP 地址。如果只需实现局域网内部的访问,则该地址可以任意。如果使用 DHCP, 网关地址可以自动获得。

(4)通讯端口 

     TCP, UDP 通讯的网络端口, 只有使用同一个端口的两个网络设备才能够相互通讯。很多通讯端口是网络通用的,如 http 端口: 80, telnet 端口: 21 等。在设置的时候注意不要使用这些端口。此外,和 PC 通讯时,要设置 PC 的防火墙,以允许这些端口的通讯。

(5)服务器模式 /客户端模式 

     表示的是模块在 TCP 通讯过程中扮演的角色。模块处于 TCP 模式并处于客户端模式时,会自动地和“服务器地址” 匹配的网络设备连接。模块处于 TCP 模式并处于服务器模式时,模块不会主动地和其他网络设备相连, 其他网络设备可以主动地连接到模块。模块处于 UDP 模式时,虽然不存在服务器/客戶端的概念。但是配置軟件上应设置成客户端模式,这样才能设置与模块通讯的远程计算机的地址。

(6)DHCP/STATIC

    打开或者关闭模块的 DHCP 功能, DHCP 功能可以使模块通过网络中的 DHCP 服务器自动获得 IP 地址,子网掩码和网关地址。

三、Linux下wifi驱动适配相关知识

     linux下wifi网卡的应用分为如下三点:

  • 根据wifi网卡芯片,配置Linux内核(配置前先得到相关网站查看相关版本内核是否支持)

  • 内核驱动支持后,移植wpa_supplicant、dhcp等软件用于操作wifi驱动,即操作wifi网卡让其作为sta模式下,连接其他AP等功能。如果要作为AP,要移植hostapd

  • 连接上后,要进行socket编程进行网络通信

1.  Linux下wifi驱动的适配

(1)WIFI网卡的选型

        选型:确定网卡的VID,PID是否在列表里:http://wireless.kernel.org/en/users/Devices/USB,下面举例说明三款wifi网卡芯片:

Atheros :  VID 0x13D3  PID 0x3327      (成品型号 AR9271)
Realtek :  VID 0x0bda   PID 0x8176      (成品型号TP-LINK公司TL-WN721N)
Realtek :  VID 0x0bda   PID 0x8178      (RTL8192CU Wireless LAN 802.11n USB 2.0 Network Adapter) RTL8192CU Wireless LAN 802.11n USB 2.0 Network Adapter

注意:
       a. USB无线网卡如果供电不足,会出现许多莫名其妙的问题
       b. 确定无线网卡的VID和PID,因为即使是同型号的网卡,可能用的芯片也不一样。确定方法是把网卡接到电脑,查看设备管理器,查看网络适配器,找到网卡后属性,详细            信息里面设备范例ID。

(2)搭建开发环境
       a. 设置VMWARE的网络为桥接, 并选择使用哪一个网卡
       b. 把PC windows网卡, vmware linux的网卡、开发板的有线网卡IP设为192.168.7.xxx,因为以后开发板上USB WIFI网卡将使用192.168.1.xxx

(3)配置内核以支持USB WIFI网卡

      a. 根据网卡的VID/PID确定使用哪一个源码
          cd drivers/net/wireless/
          grep "0x3327" * -nR     在源码里面搜索,看在哪一个文件中被使用到,搜索PID,搜索的结果如下:
                                                                                       ath/ath9k/hif_usb.c:32: { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */

     b. 打开源码所在目录的Makefile进而确定配置项的名称
         打开ath/ath9k/Makefile可知配置项为 CONFIG_ATH9K_HTC(即把此配置项配置y或m时,编译才把对应驱动编译进内核)

c. make menuconfig

   /CONFIG_ATH9K_HTC 得到下面信息(搜索CONFIG_ATH9K_HTC)
Symbol: ATH9K_HTC [=n]                                                                     |
  | Type  : tristate                                                                           |
  | Prompt: Atheros HTC based wireless cards support                                           |
  |   Defined at drivers/net/wireless/ath/ath9k/Kconfig:100                                    |
  |   Depends on: NETDEVICES [=y] && WLAN [=y] && ATH_COMMON [=n] && USB [=y] && MAC80211 [=m] |
  |   Location:                                                                                |
  |     -> Device Drivers                                                                      |
  |       -> Network device support (NETDEVICES [=y])                                          |
  |         -> Wireless LAN (WLAN [=y])                                                        |
  |           -> Atheros Wireless Cards (ATH_COMMON [=n])

  从上面可知MAC80211为m,那么对应的ATH9K_HTC也会被配置为m,所以要配置为y。

配置:
-> Networking suppor
  -> Wireless
    <*>   cfg80211 - wireless configuration API
    <*>   Generic IEEE 802.11 Networking Stack (mac80211)
    
配置上上述依赖后,就可以配置CONFIG_ATH9K_HTC为y了,如下:        
-> Device Drivers
  -> Network device support
    -> Wireless LAN
      -> Atheros Wireless Cards(如果不知道配置哪个,按H查看)
        <*>   Atheros HTC based wireless cards support          

(4) 编译内核

     make zImage

2. 使用WIFI网卡

(1)关于认证与加密

        无线加密的多种方法及其区别(WEP WPA TKIP EAP)

       http://wenku.baidu.com/link?url=DlLntlD490hAeIIbE-CO4QfAzgUC-gOTA7FCwS_XanOJMFzkyhQrFIB38ULKCcQIVFyDqqSWNWyq5kVtYAoJKjjf9pmZLu17-hVQ922WeaG

      以手机上WIFI热点为例,有4种常用的"认证/加密"
          a. open
          b. WEP
          c. WPA(TKIP)
          d. WPA2(AES)

(2)编译、使用iw,wpa_supplicant,dhcp

         a. 旧工具iwconfig, iw是它的替代者, 可用于这2种"认证/加密": open, WEP
            a.1
                  tar xzf libnl-3.2.23.tar.gz
                  cd libnl-3.2.23/
                  ./configure --host=arm-linux --prefix=$PWD/tmp  (只要看到有configure,就要配置,万能方法,--host=arm-xxx ,$PWD表示配置到当前目录)
                  修改 lib/addr.c 添加宏(宏来自内核源码,差哪个,就在内核源码搜索)
                  make
                  make install

      把编译出来的头文件应该放入:(交叉编译工具链)/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include

      cd tmp/include/libnl3
      sudo cp netlink -rf /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include(如果把libnl3全部拷贝进去,后面编译iw时会提示找不到头文件,原因就是多了一个libnl3前缀,所以只拷贝netlink即可)

      把编译出来的库文件应该放入: (交叉编译工具链中对应的目录)/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib

      把编译出来的库文件应该放入NFS文件系统的lib目录: (开发板上文件系统中对应的目录)/work/nfs_root/fs_mini_mdev_new/lib


            a.2
                  tar xjf iw-3.11.tar.bz2  (上面编译的是依赖,这里正是编译iw)
                  cd iw-3.11/
       修改Makefile:(没configure就看有没有makefile,有就修改Makefile)
       CC = "arm-linux-gcc"
       NL3xFOUND := Y  (以前makefile是通过NL3xFOUND后的命令在pc机上找使用到的libnl库,现在libnl库是给开发板用的,用原来的命令是找不出来的,所以这里直接指定,即改为Y即可。)
       #LIBS += $(shell $(PKG_CONFIG) --libs $(NLLIBNAME))
       #CFLAGS += $(shell $(PKG_CONFIG) --cflags $(NLLIBNAME))(vi文件时,打开后跳到对应行。vi makefile +76,表示打开后跳刀76行。上述两行要注释掉,否则会有警告)

       在info.c的代码前面添加(原因是htole16函数未定义,所以只需要写出这个函数即可)
       #define htole16(X)  (((((uint16_t)(X)) << 8) | ((uint16_t)(X) >> 8)) & 0xffff)

      最后把编译好的命令拷贝到开发板的bin目录

      使用:
               iw list  // 列出WIFI网卡的性能
               ifconfig wlan0 up  //启动网卡,down是关闭  lifenghu
               iw dev wlan0 scan   // 扫描WIFI AP
               iw wlan0 connect dswei  // 连接到WIFI AP:dswei (open)
               iw wlan0 connect dswei keys d:0:baiwenwang123 // 连接到WIFI AP:dswei (WEP)d: default, 0: 第0个密码
               ifconfig wlan0 192.168.1.55(开发板设置无线ip)
               ping 192.168.1.1 //ping手机

               iw wlan0 disconnect

       b. wpa_supplicant

        可用于上述4种"认证/加密",还用iw的原因是它某些功能很好用,比如扫描周围的热点。
         b.1 先编译它的依赖libopenssl 

tar xzf openssl-1.0.1d.tar.gz
cd openssl-1.0.1d/
./config shared no-asm --prefix=$PWD/tmp
修改Makefile:
CC= arm-linux-gcc  
AR= arm-linux-ar $(ARFLAGS) r
RANLIB= arm-linux-ranlib
NM= arm-linux-nm
MAKEDEPPROG= arm-linux-gcc

make   (make > log.txt 2>&1,表示make的信息会存入log.txt文件,2>&1表示错误的信息会存入第一个文件,即log.txt文件)
make install
安装:
把编译出来的头文件应该放入:
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include

把编译出来的库文件应该放入:
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib

把编译出来的库文件应该放入NFS文件系统的lib目录:
/work/nfs_root/fs_mini_mdev_new/lib

(上述拷贝的地方都在cd openssl-1.0.1d/tmp目录)


使用:
mkdir -p /var/run/wpa_supplicant

① OPEN  //无认证
wpa_supplicant -B -c/etc/plaintext.conf -iwlan0
wpa_cli -iwlan0 status  // 查看状态
ifconfig wlan0 192.168.1.55
ping 192.168.1.1

配置文件内容为:
ctrl_interface=/var/run/wpa_supplicant
network={
        ssid="dswei"
        key_mgmt=NONE  //认证方法
}

② WEP/WEP
wpa_supplicant -B -c/etc/wep.conf  -iwlan0
wpa_cli -iwlan0 status  // 查看状态,比如是否连接上等
ifconfig wlan0 192.168.1.55
ping 192.168.1.1

配置文件:
ctrl_interface=/var/run/wpa_supplicant
network={
        ssid="dswei"
        key_mgmt=NONE
        wep_key0="baiwenwang123"
        wep_tx_keyidx=0  //使用哪个密码
}

③WPA(TKIP)
wpa_supplicant -B -c/etc/wpa-psk-tkip.conf  -iwlan0
wpa_cli -iwlan0 status  // 查看状态
ifconfig wlan0 192.168.1.55
ping 192.168.1.1

配置文件
ctrl_interface=/var/run/wpa_supplicant  # 一个目录,用于wpa_supplicant和wpa_cli的socket通信
network={
        ssid="dswei"
        proto=WPA  # proto: list of accepted protocols, 可取WPA,RSN
                   # If not set, this defaults to: WPA RSN
        key_mgmt=WPA-PSK # 认证方式
                         # If not set, this defaults to: WPA-PSK WPA-EAP
        pairwise=TKIP    # If not set, this defaults to: CCMP TKIP
        group=TKIP       # If not set, this defaults to: CCMP TKIP WEP104 WEP40
        psk="baiwenwang12"
}



④ WPA2(AES)
wpa_supplicant -B -c/etc/wpa_wpa2.conf  -iwlan0
wpa_cli -iwlan0 status  // 查看状态  ,wpa_cli之前必须运行服务程序wpa_supplicant
ifconfig wlan0 192.168.223.2  
ping 192.168.223.1

配置文件:
ctrl_interface=/var/run/wpa_supplicant
network={
                ssid="DIRECT-19-HP M252 LaserJet"
                psk="12345678sayes"
        }

另:
wpa_cli可工作于"命令模式"和"交互模式"

⑤ 配置文件里设置多个network:
ctrl_interface=/var/run/wpa_supplicant
network={
        ssid="dswei"
        psk="baiwenwang123"
}
network={
        ssid="Programer"
        psk="baiwenwang"
}

⑥ 访问外网:
修改/etc/resolv.conf添加DNS:(域名服务器,作用是把域名转换为ip)
nameserver 192.168.1.1

设置网关:  (设置路由)
route add default gw 192.168.1.1


c. dhcp
    使得WIFI网卡动态获取IP,路由等信息,以前都是给网卡手动设置ip。

c.1 编译、安装
tar xzf dhcp-4.2.5-P1.tar.gz
cd dhcp-4.2.5-P1
./configure --host=arm-linux ac_cv_file__dev_random=yes


cd bind
修改Makefile:
./configure BUILD_CC=gcc ac_cv_file__dev_random=yes --host=arm-linux --disable-kqueue

tar xzf bind.tar.gz
cd bind-9.8.4-P2
修改 lib/export/dns/Makefile.in
gen: ${srcdir}/gen.c
        ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ ${srcdir}/gen.c ${LIBS}
改为
gen: ${srcdir}/gen.c
        ${BUILD_CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ ${srcdir}/gen.c ${LIBS}

(目的是arm程序不能再pc上运行,必须用pc编译的程序)
cd ../..
make DESTDIR=$PWD/tmp install

把文件复制到NFS(进入tmp/usr/local目录)
sudo cp bin/所有文件,用*代替  /work/nfs_root/fs_mini_mdev_new/bin/
sudo cp sbin/所有文件,用*代替  /work/nfs_root/fs_mini_mdev_new/sbin/
sudo cp etc/dhclient.conf.example //work/nfs_root/fs_mini_mdev_new/etc/dhclient.conf
sudo cp etc/dhcpd.conf.example //work/nfs_root/fs_mini_mdev_new/etc/dhcpd.conf

sudo cp client/scripts/linux /work/nfs_root/fs_mini_mdev_new/etc/dhclient-script
chmod +x /work/nfs_root/fs_mini_mdev_new/etc/dhclient-script
并修改
#!/bin/bash
改为
#!/bin/sh  //嵌入式里面用的是bin/sh
(上述的做法是因为执行dhclient wlan0后,用ifconfig查看,无线网卡并没有被分配ip,况且也没什么打印出错信息,所以就man dhclient,然后看有没有debug的命令,然后再一步一步地找到的)


c.2 使用:
mkdir -p /var/db  (消除一个警告信息)
wpa_supplicant -B -c/etc/wpa_wpa2.conf  -iwlan0  //连接wifi
dhclient wlan0  //连接上wifi后,执行此命令就会自动分配ip,dns,网关等,如果是外网的话

一接入WIFI网卡(把wifi网卡插上USB口,就会触发mdev,然后mdev就会根据mdev.conf文件执行auto_wifi.sh脚本),就自动执行wpa_supplicant等,即连接AP。
cat /etc/mdev.conf
wlan0 0:0 777 * /sbin/auto_wifi.sh

cat /sbin/auto_wifi.sh
#!/bin/sh
if [ $ACTION = "add" ];
then  //如果是连上网卡                                             
   wpa_supplicant -B -c/etc/wpa_wpa2.conf  -iwlan0
   wpa_cli -a/sbin/wpa_action.sh -B  //wpa_action.sh脚本在下面会描述
else   //如果是断开网卡                 
   killall wpa_supplicant
   killall wpa_cli
   killall dhclient
fi

chmod +x /sbin/auto_wifi.sh

一连接上WIFI AP, 就自动执行 dhclient,详看如下脚本
创建一脚本:    
cat /sbin/wpa_action.sh
#!/bin/sh
IFNAME=$1  //是哪个网卡
CMD=$2        //执行的动作
if [ "$CMD" = "CONNECTED" ]; then
   echo connect $IFNAME, dhclient for it > /dev/console
   dhclient $IFNAME
fi
if [ "$CMD" = "DISCONNECTED" ]; then
   echo disconnect $IFNAME, kill dhclient for it > /dev/console
   killall dhclient
fi

//退出上述脚本,在命令行执行如下命令
chmod +x /sbin/wpa_action.sh

wpa_cli -a/sbin/wpa_action.sh -B //在终端上执行命令,当wpa_supplicant发现wifi网卡连接上了AP后,就会给wpa_cli发一个事件,wpa_cli就会执行wpa_action.sh脚本。


(3)使用WIFI网卡的AP功能

参考: 移植hostapd,搭建无线热点 - 积水成渊 - 博客频道 - CSDN.NET.htm   http://blog.csdn.net/daydring/article/details/16337047

(3).1 下载源码: http://w1.fi/hostapd/
(3).2 编译、安装
tar xzf hostapd-2.0.tar.gz
cd hostapd-2.0/
cd hostapd/
cp defconfig .config
修改.config, 加一行: CONFIG_LIBNL32=y
修改Makefile:
CC=arm-linux-gcc
make
make DESTDIR=$PWD/tmp install

把生成的hostapd  hostapd_cli复制到NFS的bin目录

(3).3 使用
a. hostapd的配置文件: WPA/WPA2
ctrl_interface=/var/run/hostapd //启动下面的hostapd -B /etc/myhostapd.conf后,让一个sta连接上此ap,否则执行hostapd_cli会提示连接不上hostapd
#change wlan0 to your wireless device
interface=wlan0
driver=nl80211
ssid=S3C2440
channel=1

# 认证/加密方式
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=3
wpa_passphrase=baiwenwang
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

把配置文件存为/etc/myhostapd.conf
启动 hostapd: hostapd -B /etc/myhostapd.conf

b. 启动 dhcpd  (在开发板上启动此服务的目的是给所有要连接此ap的sta模块分配ip)
修改配置文件/etc/dhcpd.conf,添加:
subnet 192.168.1.0 netmask 255.255.255.0 {                       
  range 192.168.1.10 192.168.1.100; //分配ip范围                             
  option domain-name-servers 192.168.1.1;                        
  option routers 192.168.1.1;                                    
}    

创建空文件/var/db/dhcpd.leases:
fengel# > /var/db/dhcpd.leases  //“>”表示创建一个文件,内容为空

ifconfig wlan0 192.168.1.1  //给网卡配置一个ip
dhcpd -cf /etc/dhcpd.conf wlan0


使用hostapd_cli查看相关信息:
    与wpa_cli一样,有两种工作模式,一种是命令模式,即直接写命令;另一种是交互模式,即直接执行
hostapd_cli进入,然后就可以输入各种命令。比如执行all_sta,即查看有多少过sta连接上了此ap。如果
要看sta的ip,就要进入dhcpd.leases里面看:vi /var/db/dhcpd.leases

(3).4 OPEN方式的配置文件
ctrl_interface=/var/run/hostapd
#change wlan0 to your wireless device
interface=wlan0
driver=nl80211
ssid=S3C2440
channel=1

# 认证/加密方式
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0

(3).5 WEP方式的配置文件
ctrl_interface=/var/run/hostapd
#change wlan0 to your wireless device
interface=wlan0
driver=nl80211
ssid=S3C2440
channel=1

# 认证/加密方式
macaddr_acl=0
auth_algs=2
ignore_broadcast_ssid=0
wep_key0="baiwenwang123"
wep_default_key=0

(3).6 修改/etc/mdev.conf自动启动AP模式
cat /etc/mdev.conf
wlan0 0:0 777 * /sbin/auto_wifi_ap.sh

cat /sbin/auto_wifi_ap.sh   //auto_wifi_ap.sh文件一定要可执行
#!/bin/sh
if [ $ACTION = "add" ];
then
   hostapd -B /etc/myhostapd.conf
   ifconfig wlan0 192.168.1.1
   dhcpd -cf /etc/dhcpd.conf wlan0
else
   killall hostapd
   killall dhcpd
fi

注意事项:
对于包含了AR9271网卡驱动的内核,有一个问题:
在上电之前就接上了网卡,那么系统启动后无法识别出这个网卡。
解决方法:
a.上电后再接网卡
b.把驱动编译为模块,当系统启动后再insmod: 可以在上电之前就接网卡
编译为模块的方法:
make menuconfig
device drivers->network device support->Wireless LAN->Atheros Wireless Cards
->Atheros HTC based wireless cards supports  这个选项要选为M,
然后执行make zImage && make modules命令
然后在把/drivers/net/wireless/ath/ath9k/所有(用*代替所有).ko 拷贝到开发板相应目录
然后在启动脚本中装载,注意装载顺序,即:
insmod ath9k_hw.ko
insmod ath9k_common.ko
insmod ath9k_htc.ko

(可能原因:ath9k_htc.ko要用到固件, 但是固件要到根文件系统被挂载后才能访问)

四、wifi打印相关知识

1.Linux下socket编程

      上面介绍了在linux下如何使用wifi网卡,wifi网卡驱动适配上后,就可以在linux应用层进行网络编程了。下面是自己设计的简单的网络通信的例子:

socket-client.c:

/*
*linux下网络编程资料:  
*http://blog.csdn.net/xrb66/article/details/6048399
*
*/

#include <stdint.h>
#include <stdio.h>      
#include <stdlib.h>    
#include <unistd.h>     
#include <sys/types.h>  
#include <sys/stat.h> 
#include <fcntl.h>      
#include <termios.h>    
#include <errno.h>      
#include <string.h>
#include <sys/time.h>
#include <sys/ioctl.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/shm.h>

#define SERVER_PORT 9999
#define BUFFER_SIZE 4097

int socket_send_pack(int sockfd,const void * buf,size_t len,int flags);

int main()
{
	char socketSendbuf[BUFFER_SIZE];
	
    char recvbuf[BUFFER_SIZE];
	int recvFlag=0;
	
	int sendReturn = 0;
	int realReadFileLengh =0;
	
	char * file_name = "/home/6.pdf";
	//char * file_name = "./123.txt";
	
    //定义sockfd
    int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
	if( -1 == sock_cli )
	{
		printf("\nclient socket err,exit!\n");
        exit(1);
	}

    //定义sockaddr_in
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVER_PORT);  //Server port
    //servaddr.sin_addr.s_addr = inet_addr("192.168.223.1");  ///server ip
	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	memset(servaddr.sin_zero, 0, 8);
	
	
    //connect server,on success return 0,err will return -1
    if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
		printf("\nclient connect err!,exit!\n");
        exit(1);
    }

    memset(socketSendbuf, 0, sizeof(socketSendbuf));
	
	FILE *readFileFp = fopen(file_name, "r");
	if(NULL == readFileFp) //if failed,fread and fwrite can't go on 
    { 
		printf("file open failed,exit!\n"); 
		exit(1);
    } 
	
    while(1) 
	{
	/*
		fread or fwrite does not distinguish between end-of-file and error, and callers must use feof(3)
		and ferror(3) to determine which occurred.
	*/
		realReadFileLengh = fread(socketSendbuf,1, 4096, readFileFp);//return value equals the number of bytes transferred only when the second parameter is 1.
		
		if( ferror(readFileFp) )
		{
			printf("client: file read err, ferror(readFileFp)=%d\n",ferror(readFileFp));
			clearerr(readFileFp);//Reset error markers and feof(readFileFp)
			fclose(readFileFp); 
			close(sock_cli);
			exit(1);
		}
		
		if( realReadFileLengh >0 )
		{
			//socketSendbuf[realReadFileLengh] = '\0';
			//printf("\n %s \n",socketSendbuf);
			sendReturn = socket_send_pack(sock_cli,socketSendbuf,realReadFileLengh,0);
			if( sendReturn <= 0 )
			{
				printf("client: send failed,break\n");
				break;
			}
			memset(socketSendbuf, 0, sizeof(socketSendbuf));
		}
		else
		{
			//feof(readFileFp);
			printf("client: file read end, socket send end!\n");
			break;
		}
		
	}
	fclose(readFileFp); 
	
	
	
   // while( (recvFlag = recv(sock_cli, recvbuf, sizeof(recvbuf),0)) > 0 ) ///rev
	//{
	//	printf("recvFlag = %d\n",recvFlag);
   // } 
		
	//printf("%s\n", recvFlag);

	
	
    close(sock_cli);
	printf("client:close the socket ,client program return\n");
	return 0;
}



ssize_t socket_send_pack(int sockfd,const void * buf,size_t len,int flags)//size_t: size_type,Indicates the size of the type ... 
{
  if(buf==NULL||len<=0)
    return 0;
 
    size_t nleft;
    ssize_t realSendLengh;
    const char * ptr;
 
  ptr = (const char *)buf;//man or woman is people,But people not always man or woman. so (const char *)
  nleft = len;
 
    while(nleft>0)
    {
        if( (realSendLengh = send(sockfd, ptr, nleft,flags)) <= 0 )//System call failure
        {
            if( (realSendLengh <=0) && (errno == EINTR) )		//Interrupted by signal,retransmit
               realSendLengh=0;
            else					//Otherwise is the real send failure
               return -1;
        }
				
       //Adjust offset
       nleft-=realSendLengh;
       ptr+=realSendLengh;
    }
    return len;
}

socket-server.c:

/*
*linux下网络编程资料:  
*http://blog.csdn.net/xrb66/article/details/6048399
*
*/

#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h> 
#include <stdint.h>
#include <stdlib.h>    
#include <sys/stat.h> 
#include <fcntl.h>      
#include <termios.h>    
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/shm.h>

ssize_t socket_recv_pack(int sockfd,void * buf,size_t len, int flags);

/* socket
 * bind
 * listen
 * accept
 * send/recv
 */

#define SERVER_PORT 9999
#define BACKLOG     10   //link number
#define BUFFER_SIZE 4097

char * writeFileName = "./321.txt";


int main(int argc, char **argv)
{
	int iSocketServer = 0;
	int iSocketClient = 0;
	struct sockaddr_in tSocketServerAddr;
	struct sockaddr_in tSocketClientAddr;
	int iRet = 0;
	int iAddrLen = 0;

	int recvReturn = 0;

	int realWriteFileLengh =0;	

    char recvbuf[BUFFER_SIZE];

	FILE *writeFp = fopen(writeFileName, "w");
	if(NULL == writeFp) //if failed,fread and fwrite can't go on 
    { 
		printf("writeFile open failed,return!\n"); 
		return -1;
    } 
	
	iSocketServer = socket(AF_INET, SOCK_STREAM, 0);
	if (-1 == iSocketServer)
	{
		printf("socket error!,return main\n");
		return -1;
	}

	

//服务器端是被动地响应请求的,所以要不断地监测某个端口(服务器端端口),才知是否有数据
//所以bind函数是把socket返回的fd与自己的ip、端口绑定起来。	
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!,return main\n");
		return -1;
	}

//启动监测数据,iSocketServer即监听相应ip对应的端口,第二个参数表示可以同时检测多少路数据
	iRet = listen(iSocketServer, BACKLOG);
	if (-1 == iRet)
	{
		printf("listen error!,return main\n");
		return -1;
	}

	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
/*
	TCP是可靠传输,所以在传输前要先建立一条连接。accept就是接受客户端一
条连接请求(客户端通过connect函数来建立),一开始调用会睡眠并等待客户端
的连接请求,如果客户端来连接了,那么ip等信息就会保存在参数tSocketClientAddr里
如果成功,就会返回一个非负的客户端描述符,服务器端接收数据时用到
*/
		iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
		if (-1 != iSocketClient)
		{
			printf("Get connect from client : %s\n", inet_ntoa(tSocketClientAddr.sin_addr));//inet_ntoa函数用于转换为常用字符串
			
			while (1)
			{
				recvReturn = socket_recv_pack(iSocketClient,recvbuf,4096,0);
				if( recvReturn <= 0 )
				{
					printf("server: recv failed,break while(1)\n");
					break;
				}
				else
				{
					realWriteFileLengh = fwrite(recvbuf,1,recvReturn,writeFp);
					if( ferror(writeFp) )
					{
						printf("server: file write err, ferror(writeFp)=%d\n",ferror(writeFp));
						clearerr(writeFp);//Reset error markers and feof(writeFp)
						fclose(writeFp); 
						close(iSocketClient);
						close(iSocketServer);
						return -1;
					}
					
				}
			}				
			
		}
		fclose(writeFp);//must close,otherwise can't write success
		
	}
	
	close(iSocketServer);
	printf("\nserver program return\n");
	return 0;
}


ssize_t socket_recv_pack(int sockfd,void * buf,size_t len, int flags)//size_t: size_type,Indicates the size of the type ... 
{
	if(buf==NULL||len<=0)
		return 0;
 
	size_t nleft;
	ssize_t realRecvLengh;
	char *ptr;
 
	ptr = (char *)buf;//man or woman is people,But people not always man or woman. so (const char *)
	nleft = len;
 
    while(nleft>0)
    {
         if( (realRecvLengh = recv(sockfd,ptr,nleft,0)) < 0 )//System call failure,-1
         {
                if( errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN )//是由于信号中断造成的读失败,则继续读
                   realRecvLengh=0;
                else//否则是真正的读错误,返回失败的标志
                   return -1;
         }
         else
             if( 0 == realRecvLengh )//另一端已关闭连接,这种关闭是对方主动且正常的关闭
                break;
 
 
		 //Adjust offset
         nleft-=realRecvLengh;//剩余要读取的
         ptr+=realRecvLengh;//偏移缓冲区位置
 
   }
 
    return (len-nleft);
}

2. 网络打印的两个基本端口

      通过对HP的一台具备WIFI功能的激光打印的网络抓包破解,发现网络通信端口为9100,9100相关内容如下(下面内容来自于网上):

      打印设备和主机的连接方式(printer interface)形态多样,从历史悠久的串口并口到现在流行的网络打印和USB连接,另类的红外连接和蓝牙技术,还有超炫的火线连接(IEEE 1394)。

      网络打印最大的好处就是空间上不受限制,不被串口线/并口线/USB线的长度所禁锢,北京办公室的员工可以直接把文件打印到上海办公室老板身边的打印机,这要感谢TCP/IP协议族建立的强大的通讯基础设施。

      伴随着TCP/IP的诞生和发展,人们立即把这项技术应用到打印领域,比较早形成标准的就是 Line Printer Daemon Protocol,通称为 LPR 协议,记录在 RFC1179 文档中。LPR 协议在Unix系统上广泛应用和实现(那时候还没有Windows)。LPR协议规定发送方的端口从721到731,接收方端口是515。

      当HP公司推出JetDirect打印机系列的时候,他们没有在他们的打印服务器上采用LPD协议,而是开发了一种新的网络打印协议,这个新协议被称为 RAW 打印协议或 Socket API。打印设备上开启的TCP端口是9100,这个端口提供到打印引擎(print engine)的直接连接,类似于以前的串口或并口,这也就是它被称为 RAW 的原因。这个连接通常是全双工的,并在打印时提供错误报告和状态信息。

     花开两朵,各表一枝。我们回头再谈LPR和9100传输的细节问题,先看一下网络打印技术在Windows操作系统上的发展。这里只讲Win OS作为打印客户端的情况,Win OS作为打印服务器的情况不在讨论之列。编辑/查看文档的应用程序,比如MS Word/Excel/PPT,Notepad,Adobe Acrobat等,不会直接跟网络打印设备建立连接。当我们从这些程序打印文档的时候,操作系统上有一类叫做端口监视器(Port Monitor)的程序在运行,它们把客户端连接到对应的打印机上。在Win2000之前,端口和port monitor的种类比较多也比较乱,因为那时打印行业标准还不统一。每个打印设备生产商如果定义了自己的接口,就要有相应的端口类型和port monitor。比如安装在WinNT4上的Digital Network port monitor,Hewlett-Packard JetAdmin,和Lexmark Port Monitors。我们可以通过打印机属性页看到自己电脑上安装的端口类型,每个类型都有自己的port monitor。

      从Win2000起,微软推出了Standard TCP/IP Port Monitor(SPM),SPM跟打印设备建立TCP连接。SPM是一种服务,而不是一个协议。SPM可以使用 RAW 或 LPR 协议向打印机发送作业。对大多数打印设备来说,RAW是默认的协议。如果在端口配置中选择了LPR 协议,SPM 就用LPR协议发送作业。在Win2k和WinXP上还可以看到LPR Port和LPR Port Monitor,请不要把LPR Port和LPR 协议混淆在一起,虽然它们是有联系的。LPR Port默认情况下不会安装,需要在“添加/删除Windows组件”中选择“Other Network File and Print Services”——>“Print Services for Unix”。从细节上讲,LPR Port是由lprmon.dll来管理的,而SPM是由tcpmon.dll来执行的。
      SPM中实现的LPR协议跟标准的LPR协议还是有所不同的。标准的LPR协议使用端口 721到731来发送数据,Windows SPM在使用LPR协议时则使用>1023的未保留的端口。另外 一个不同是,SPM向spooler发送打印作业时无需确定作业的大小,而标准的LPR协议规定打印作业必须包含作业大小的信息。这样的话,标准的LPR Port Monitor就要 spool 作业两次 — 一次确定作业大小,一次把作业发给spooler。相比之下,SPM Spool作业一次,提高了打印效率。

     可以比较一下网络上抓下来的标准LPR包和SPM实现的LPR包。
标准LPR包:
Tcp: SrcPort=XSRP(721), DstPort=LPD(515)  //注:源端口在721-731之间
SPM实现的LPR包:
Tcp: SrcPort=1844, DstPort=LPD(515)  //注:源端口>1023
它们的源端口差别如上文所述,目标端口是一致的,另外,我这里没贴出来的,LPR协议本身携带的数据在两种情况下是一致的。

      再回过头来看9100端口和LPD端口配置的不同。
LPR协议因为起源的原因,规定了line printer daemon客户端和服务端交互的一系列命令,大概的内容如下:
switch(command code){
case 01:
            Print any waiting jobs;
case 02:
            //Receive a printer job;
            //second level commands
            Send positive acknowledgement;
            switch(subcommands code)
             {
             case 01:
                          Abort job;
             case 02:
                          Send positive acknowledgement;
                          Receive control file;
             case 03:
                          Send positive acknowledgement;
                          Receive data file;
             }
case 03:
             Send queue state (short);
case 04:
             Send queue state (long);
case 05:
             Remove jobs;
}
LPR协议规定的一套逻辑细节请参看RFC1179。

      可以看到,这些命令对我们现在打印的要求来说似乎有些繁琐,HP当年设立9100端口的意思大概也是跳过这些命令来往,直接把准备好的PDL(page description language)数据扔给打印引擎,RAW数据就是PDL用的数据类型,PCL和PostScript都是RAW数据,打印引擎可以直接处理。
      通过比较同一个作业分别用9100和LPR端口发的数据包,我们可以看到,LPR子命令发送的“Data File”的内容跟TCP协议9100端口发出去的数据内容是一样的。这个数据内容,我们可以用具体打印机的“Print to file”方式得到。
      SPM用9100端口向打印设备发送打印数据,作业完成后就关闭连接。对打印机的管理则遵照RFC 1759(Printer MIB)用SNMP协议来进行,LPR端口则是数据和控制信息都在一个连接上处理。打个比方,9100端口是双车道,数据和控制信息分开走,LPR则是单车道。
      简而言之,9100端口打印更加高效快捷,更具有扩展性。

     因此,只要将通信端口设置为9100,并且把arm上的wifi网卡设置为sta模式,这样就就可以与wifi打印机进行通信了。当然,通信的时候要注意打印机语言,在通过wifi网络传输数据的时候一定要安装打印机支持的打印语言传输数据报文。另外,默认情况下是在TCP通信中把打印机作为服务器端。



































  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值