【入门到精通】鸿蒙next开发:基于wifiManager实现P2P连接

往期鸿蒙5.0全套实战文章必看:(文中附带全栈鸿蒙5.0学习资料)


基于wifiManager实现P2P连接

WiFi P2P简介

基本原理

WiFi Direct协议是Wi-Fi联盟发展、支持与授予认证的一套软件协议,也被称为Wi-Fi点对点(Wi-Fi Peer-to-Peer,简称P2P)。这套协议允许无线网络中的设备无需通过无线路由器即可相互连接,以点对点的方式直接与另一个 WiFi 设备连线,进行数据高速传输。

通常A与B通信是通过服务器转发数据。

22.png

P2P则可以实现A与B直接通信。

23.png

技术特点

  • 连接方式:允许 WiFi 设备直接连接,无需通过 AP,从而简化连接流程,提高了数据传输的便捷性。
  • 传输性能:在传输速度与传输距离方面比蓝牙有大幅度提升,最大传输距离可达 200 米,最大传输速度为 250Mbps。
  • 加密机制:支持 WPA2 加密机制,确保数据传输的安全性。

应用场景

  • 文件传输:可以在手机和平板之间快速传输照片、视频等大文件。
  • 内容共享:在会议中直接通过电脑展示手机内容,或在不同设备间共享应用。
  • 文档打印:直接连接打印机进行打印。
  • 数据同步:在设备间同步数据。
  • 娱乐应用:支持近距离的设备互联,适用于游戏、聊天、车机交互。

方案描述

通过wifiManager实现P2P连接,前提需要打开设备WLAN开关,整体方案分为建立P2P连接和P2P连接场景验证两个部分:

  • 建立P2P连接: 发现设备并与P2P设备建立连接。
  • P2P连接场景验证:验证P2P连接后的socket通信,模拟用户与车机交互。

建立P2P连接

1、发现设备:P2P连接需要先发现P2P设备才能进行连接。

a、注册发现设备状态监听。注册发现设备状态改变事件,注册事件可通过回调监听设备发现服务是否开启成功。

aboutToAppear(): void { 
  // 注册发现设备状态监听 
  wifiManager.on("p2pDiscoveryChange", this.recvP2pDiscoveryChangeFunc); 
}

在业务退出时,要调用wifiManager.off('p2pDiscoveryChange')接口注销注册回调。

aboutToDisappear(): 
  // 注销发现设备状态监听 
  wifiManager.off("p2pDiscoveryChange", this.recvP2pDiscoveryChangeFunc); 
}

发现设备回调事件: 0- 初始状态。 1-发现成功。

// 发现设备状态改变事件。 
recvP2pDiscoveryChangeFunc = (result: number) => { 
  promptAction.showToast({ 
    message: result == 1 ? '发现设备成功' : '发现设备失败', 
    duration: 2000 
  }); 
}

开始发现设备,wifiManager.startDiscoverDevices接口为开启P2P发现设备关键步骤,发现设备状态结果通过监听事件回调。

Button('开始发现设备').onClick(() => { 
  try { 
    wifiManager.startDiscoverDevices(); 
  } catch (error) { 
    console.error("wifiManager.startDiscoverDevices failed:" + JSON.stringify(error)); 
  } 
})

b、获取设备列表。

当发现设备阶段完成,即发现设备状态监听事件回调为1,此时设备可被p2p设备发现,且通过wifiManager.getP2pPeerDevices可获取对端设备列表。

// 获取P2P对端设备列表信息 
getPeerDeviceList() { 
  // p2p发现阶段完成,才能正常获取到对端设备列表信息 
  this.peerDevices = [] 
  wifiManager.getP2pPeerDevices((err, data) => { 
    if (err) { 
      console.error("get P2P peer devices error"); 
      return; 
    } 
    console.info("get P2P peer devices: " + JSON.stringify(data)); 
    this.peerDevices = data 
  }); 
}

2、建立连接。

a、通过已发现设备WifiP2pDevice进行连接。

建立p2p连接会有连接状态回调,通知连接状态变化,可根据状态变化实现对应逻辑。首先声明监听事件recvP2pConnectionChangeFunc。

// p2p连接状态改变事件 
recvP2pConnectionChangeFunc = (result: wifiManager.WifiP2pLinkedInfo) => { 
  console.info("p2p connection change receive event: " + JSON.stringify(result)); 
  if (result.connectState == 1) { 
    promptAction.showToast({ 
      message: '已连接', 
      duration: 2000 
    }); 
  } 
}

再通过wifiManager.on("p2pConnectionChange")注册p2p连接状态监听。

aboutToAppear(): void { 
  // 注册p2p连接状态监听 
  wifiManager.on("p2pConnectionChange", this.recvP2pConnectionChangeFunc) 
}

p2p连接状态监听在业务结束时通过wifiManager.off("p2pConnectionChange")注销。

aboutToDisappear(): void { 
  // 注销p2p连接状态监听 
  wifiManager.off('p2pConnectionChange',this.recvP2pConnectionChangeFunc) 
}

从扫描到的设备列表中,选择需要连接的设备通过wifiManager.p2pConnect进行P2P连接。

// 建立对端连接 
connectToPeerDevice(device: wifiManager.WifiP2pDevice) { 
  let config: wifiManager.WifiP2PConfig = { 
    deviceAddress: device.deviceAddress, 
    deviceAddressType: device.deviceAddressType, 
    netId: 0, 
    passphrase: "", 
    groupName: "", 
    goBand: 0, 
  } 
  try { 
    wifiManager.p2pConnect(config); 
  } catch (e) { 
    console.error("wifiManager.p2pConnect error ", e.code); 
  } 
}

b、获取P2P连接群组信息。

p2p连接成功后获取当前群组信息,获取goIpAddress,通过goIpAddress可与对端服务进行通信。

// 获取当前群组信息 
getGroupInfo(){ 
  wifiManager.getCurrentGroup((err, data) => { 
    if (err) { 
      console.error("get current P2P group error"); 
      return; 
    } 
    console.info("get current P2P group: " + JSON.stringify(data)); 
    this.goIpAddress = data.goIpAddress 
  }); 
}

P2P连接场景验证:

1、手机模拟车机系统。

效果图:用户连接车机socket成功

24.jpg

const tcpServer = socket.constructTCPSocketServerInstance()
export function createServer(callback: Callback<boolean>): void { 
  let ipAddress : socket.NetAddress = {} as socket.NetAddress 
  ipAddress.address = "0.0.0.0" 
  ipAddress.port = 4651 
  tcpServer.listen(ipAddress, (err: BusinessError) => { 
    if (err) { 
      console.log("listen fail"); 
      return 
    } 
    console.log("listen success"); 
    promptAction.showToast({ 
      message: JSON.stringify('listen success'), 
      duration: 2000 
    }) 
  }) 
 
  class SocketInfo { 
    message: ArrayBuffer = new ArrayBuffer(1); 
    remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 
  } 
 
  // Listen client connect to server 
  tcpServer.on("connect", (connection: socket.TCPSocketConnection) => { 
    tcpConnectArray.pop() 
    tcpConnectArray.push(connection) 
 
    // Listen connection closed 
    connection.on("close", () => { 
      console.info("on close success") 
    }); 
 
    // Listen receive message 
    connection.on("message", (value: SocketInfo) => { 
      let buffer = value.message 
      let dataView = new DataView(buffer); 
      let str = "" 
      for (let i = 0; i < dataView.byteLength; ++i) { 
        str += String.fromCharCode(dataView.getUint8(i)) 
      } 
      // Response to client 
      response() 
      // Toast message 
      promptAction.showToast({ 
        message: JSON.stringify(str), 
        duration: 2000 
      }) 
    }) 
 
    // Send data to the client for Connection state. 
    let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions 
    tcpSendOptions.data = 'Hello, client, connect success!' 
    connection.send(tcpSendOptions, (err: BusinessError) => { 
      if (err) { 
        console.log("send fail") 
        return 
      } 
      console.log("send success") 
    }) 
  }) 
}

2、手机应用连接车机服务

效果图:连接车机socket成功

25.jpg

通过p2p连接获取到的goIpAddress连接车机Socket服务:

// 连接车机Socket服务 
createSocketClient(){ 
  let ipAddress: socket.NetAddress = {} as socket.NetAddress; 
  ipAddress.address = this.goIpAddress; 
  ipAddress.port = 4651; 
  let tcpConnect: socket.TCPConnectOptions = {} as socket.TCPConnectOptions; 
  tcpConnect.address = ipAddress; 
  tcpConnect.timeout = 6000; 
  tcp.connect(tcpConnect, (err: BusinessError) => { 
    if (err) { 
      console.log('connect fail' + JSON.stringify(err)); 
      return; 
    } 
    console.log('connect success'); 
  }); 
}

3、手机应用向车机服务发送消息

效果图:车机收到用户发送的‘hello,my car!’

26.jpg

// 发送消息 
let clientSendOptions: socket.TCPSendOptions = {} as socket.TCPSendOptions; 
export function sendMsg() { 
  clientSendOptions.data = 'hello,my car!'; 
  tcp.send(clientSendOptions, (err: BusinessError) => { 
    if (err) { 
      console.log('sendMsg fail '); 
      return; 
    } 
    console.warn('fxm debug : client sendMsg success'); 
  }) 
}

4、车机服务响应手机应用消息

效果图:用户收到车机响应的‘hello,have a good day!’

27.jpg

在创建的车机socket server中,有接受消息的监听,监听到手机应用请求后,做出响应。

export function response() { 
  let connection: socket.TCPSocketConnection = tcpConnectArray[0]; 
  let tcpSendOptions: socket.TCPSendOptions = {} as socket.TCPSendOptions 
  tcpSendOptions.data = 'hello,have a good day!' 
  connection.send(tcpSendOptions, (err: BusinessError) => { 
    if (err) { 
      console.log("response fail") 
      return 
    } 
    console.log("response success") 
  }) 
}

5、车机服务向手机应用推送消息

效果图:用户收到车机推送的‘hello, the car has reached its destination!’

28.jpg

车机系统也可向手机应用主动推送消息。

let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions 
tcpSendOptions.data = 'hello, the car has reached its destination!' 
connection.send(tcpSendOptions, (err: BusinessError) => { 
  if (err) { 
    console.log("send fail") 
    return 
  } 
  console.log("send success") 
})

到此则实现p2p连接后的socket通信验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值