HarmonyOS 鸿蒙Next:新建并打开两个模拟器,如何使用网络将其互联?

发布于 1周前 作者 gougou168 来自 鸿蒙OS

HarmonyOS 鸿蒙Next:新建并打开两个模拟器,如何使用网络将其互联?

使用DevEco 最新版,并且模拟器也是最新,可新建两个模拟器并独立运行。现想使用网络将其互联,实现互通,请问各位有无实现思路。个人猜想是,新建模拟器A、B,在模拟器B 上配置网络代理。但无法实现

11 回复

cke_872.png

针对14楼我遇到的情况,我提交了一个工单。官方回复如下,等了一周多。

典型的场景、是模拟器需要和一个物联网设备进行udp通讯。

本文概述

  • 问题背景:由于缺少HarmonyOS NEXT 真机,无法处理网络互通测试需求。因此,尝试探索模拟器互通

  • 环境准备:

  • 新建两个模拟器

    222.png

  • 运行截图:后期会考虑上传一个视频

    ​​666.png

核心步骤

  • 由于两个模拟器均位于同一PC,其IP 及端口号均一致,因此,我需做端口转发即可

  • 使用hdc 查询模拟器id 与模拟器对应关系:需提前打开模拟器

    • 概述:

      • 红色框内即为模拟器id

      • 只开一个,并执行hdc list targets 即可进行区分

        333.png

    • 对应关系:

      • 127.0.0.1:5554 对应Huawei_Phone,将其用作客户端

      • 127.0.0.1:5557 对应Huawei_Phone_New,将其用作服务端

  • 端口转发:对服务端进行端口转发

    • 执行命令

      hdc -t 127.0.0.1:5557 fport ls//查询端口转发任务
      hdc -t 127.0.0.1:5557 fport tcp:8089 tcp:8088//执行端口转发任务
    • 运行截图:

      • 第一条:此时无端口转发任务

      • 第二条:执行端口转发任务

      • 第三条:查询端口转发任务,佐证第二条是否执行成功

      444.png

代码运行步骤

  • 先运行服务端,再运行客户端

  • 详细步骤,请查阅演示视频

完整代码

  • 公共参数:InfoObject.ets

    export class InfoObject{
      messageNumber: number = 0//共计收到多少条消息
      receiveMsg: string = "默认值"//接收的消息的字面量
      ipAddress: string = "默认值"//通信对方的IP 地址
      portNumber: number = 0//通信对方的端口号
      protocolType: string = "默认值"//通信对方所采用的协议类型
      sizeMsg: number = 0//消息的字节数
    ​
      constructor(messageNumber: number,receiveMsg: string,ipAddress: string,portNumber: number,protocolType: string,sizeMsg: number) {
        this.messageNumber = messageNumber
        this.receiveMsg = receiveMsg
        this.ipAddress = ipAddress
        this.portNumber = portNumber
        this.protocolType = protocolType
        this.sizeMsg = sizeMsg
      }
    }
  • 客户端页面:TCPSocketClientPage.ets

    import { TCPSocketClientUtils } from './TCPSocketClientUtils';
    import { InfoObject } from './InfoObject'
    ​
    [@Entry](/user/Entry)
    [@Component](/user/Component)
    struct TCPSocketClientPage {
    ​
      [@State](/user/State) info: InfoObject = new InfoObject(0,"默认值","默认值",0,"默认值",0)
    ​
      tcpSocketClient: TCPSocketClientUtils = new TCPSocketClientUtils(this.info);
    ​
      build() {
        Row() {
          Column() {
            Text("此为客户端端模拟器")
              .fontSize(20)
              .fontWeight(FontWeight.Bold)
            Button("启动客户端")
              .fontSize(20)
              .onClick((event) => {
                this.tcpSocketClient.init();
              })
            Button("客户端向服务端发送数据")
              .fontSize(20)
              .onClick((event) => {
                this.tcpSocketClient.sendMsg();
              })
            Column(){
              Text("展示客户端接收的消息内容").fontColor(Color.Green)
              Text(`客户端共计收到${this.info.messageNumber} 条消息`)
              Text(`客户端接受到的NO.${this.info.messageNumber} 消息:${this.info.receiveMsg}`).fontColor(Color.Grey)
              Text(`与客户端通信的对方IP :${this.info.ipAddress}`).fontColor(Color.Orange)
              Text(`与客户端通信的对方端口号:${this.info.portNumber}`).fontColor(Color.Blue)
              Text(`与客户端通信的对方采用的协议:${this.info.protocolType}`).fontColor(Color.Pink)
            }.margin({top: 36})
          }
          .width('100%')
        }
        .height('100%')
      }
    ​
      aboutToDisappear() {
        this.tcpSocketClient.closeSocket('界面不可见');
      }
    }
  • 客户端工具类:TCPSocketClientUtils.ets

    import { socket } from '[@kit](/user/kit).NetworkKit';
    import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
    import hilog from '[@ohos](/user/ohos).hilog';
    ​
    import { InfoObject } from "./InfoObject"
    ​
    const TAG: string = "WAsbry_TCPSocketClient";
    ​
    class SocketInfo {
      message: ArrayBuffer = new ArrayBuffer(1);
      remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
    }
    ​
    export class TCPSocketClientUtils {
    ​
      info: InfoObject
    ​
      tcp: socket.TCPSocket;//TCP链接实例
    ​
      constructor(info: InfoObject) {
        // 创建一个TCPSocket连接,返回一个TCPSocket对象。
        this.tcp = socket.constructTCPSocketInstance();
        this.info = info
      }
    ​
      init() {
        printLog(TAG,"进入客户端绑定环节")
        // 绑定本地IP地址和端口。
        let ipAddress: socket.NetAddress = {} as socket.NetAddress;
        ipAddress.address = "10.0.2.15";//客户端本机IP
        ipAddress.port = 12340;//指定客户端本地端口号
        this.tcp.bind(ipAddress, (err: BusinessError) => {//绑定IP地址和端口号。端口号可以指定,也可以由系统随机分配
          if (err) {
            printLog(TAG, `客户端绑定IP地址和端口号出现异常,err = ${err}`);
            return;
          }
          printLog(TAG, '客户端绑定IP地址和端口号成功');
    ​
          // 连接到指定的IP地址和端口。
          ipAddress.address = "10.0.2.2";
          ipAddress.port = 8089;
    ​
          let tcpConnect: socket.TCPConnectOptions = {} as socket.TCPConnectOptions;
          tcpConnect.address = ipAddress;
          tcpConnect.timeout = 30000;
    ​
          this.tcp.connect(tcpConnect).then(() => {
            printLog(TAG, '客户端建立到指定IP地址和端口号的连接,成功');
            // this.sendMsg();
          }).catch((err: BusinessError) => {
            printLog(TAG, '客户端建立到指定IP地址和端口号的连接,出现异常');
          });
        });
    ​
        this.tcp.on('message', (value: SocketInfo) => {
          printLog(TAG,"客户端 TCPSocketConnection成功接收到消息")
          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));
          }
    ​
          printLog(TAG, "客户端 received message--:" + str);//消息内容
          printLog(TAG, "客户端 received address--:" + value.remoteInfo.address);//绑定的IP地址。
          printLog(TAG, "客户端 received family--:" + value.remoteInfo.family);//网络协议类型。选项包括:IPv4、IPv6。
          printLog(TAG, "客户端 received port--:" + value.remoteInfo.port);//端口号。取值范围是0 ~ 65535。
          printLog(TAG, "客户端 received size--:" + value.remoteInfo.size);//服务器响应消息的长度,以字节为单位。
    ​
          this.info.messageNumber++
          this.info.receiveMsg = str
          this.info.ipAddress = value.remoteInfo.address
          this.info.protocolType = value.remoteInfo.family
          this.info.portNumber = value.remoteInfo.port
          this.info.sizeMsg = value.remoteInfo.size
        });
        this.tcp.on('connect', () => {
          printLog(TAG, "客户端TCPSocket连接建立");
        });
        this.tcp.on('close', () => {
          printLog(TAG, "客户端TCPSocket连接关闭");
        });
    ​
      }
    ​
      sendMsg(){
        let tcpSendOptions: socket.TCPSendOptions = {
          data: 'this data is from client'
        }
        this.tcp.send(tcpSendOptions).then(() => {
          printLog(TAG, '客户端向服务端发送数据成功');
        }).catch((err: BusinessError) => {
          printLog(TAG, '客户端向服务端发送数据失败');
        });
      }
    ​
      closeSocket(reason: string) {
        this.tcp.close().then(() => {
          printLog(TAG, reason + ' 客户端到服务端的链接关闭,成功');
        }).catch((err: BusinessError) => {
          printLog(TAG, reason + ' 客户端到服务端的链接关闭,出现异常');
        });
        this.tcp.off('message');
        this.tcp.off('connect');
        this.tcp.off('close');
      }
    }
    ​
    function printLog(tag: string,info: string){
      hilog.info(0xff00,tag,info)
    }
  • 服务端页面:TCPSocketServerPage.ets

    import { InfoObject } from './InfoObject';
    import { TCPSocketServerUtils } from './TCPSocketServerUtils';
    ​
    [@Entry](/user/Entry)
    [@Component](/user/Component)
    struct TCPSocketServerPage {
    ​
      [@State](/user/State) info: InfoObject = new InfoObject(0,"默认值","默认值",0,"默认值",0)
    ​
      tcpSocketServer: TCPSocketServerUtils = new TCPSocketServerUtils(this.info);//创建tcp 服务端工具类对象
    ​
      build() {
        Row() {
          Column() {
            Text("此为服务端模拟器")
              .fontSize(20)
            Button('启动服务端')
              .fontSize(20)
              .onClick((event) =>{
                this.tcpSocketServer.init();
              })
            Button('服务端向客户端发送数据')
              .fontSize(20)
              .onClick((event) =>{
                this.tcpSocketServer.sendMsg();
              })
            Column(){
              Text("展示服务端接收的消息内容").fontColor(Color.Green)
              Text(`服务端共计收到${this.info.messageNumber} 条消息`)
              Text(`服务端接受到的NO.${this.info.messageNumber} 消息:${this.info.receiveMsg}`).fontColor(Color.Grey)
              Text(`与服务端通信的对方IP :${this.info.ipAddress}`).fontColor(Color.Orange)
              Text(`与服务端通信的对方端口号:${this.info.portNumber}`).fontColor(Color.Blue)
              Text(`与服务端通信的对方采用的协议:${this.info.protocolType}`).fontColor(Color.Pink)
            }.margin({top: 36})
          }
          .width('100%')
        }
        .height('100%')
      }
    ​
      aboutToDisappear() {
        this.tcpSocketServer.closeClient();
        this.tcpSocketServer.cancelEventSub();
      }
    ​
    }
  • 服务端工具类:TCPSocketServerUtils.ets

    import { socket } from '[@kit](/user/kit).NetworkKit';
    import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
    import hilog from '[@ohos](/user/ohos).hilog';
    import { InfoObject } from './InfoObject';
    ​
    const TAG: string = "WAsbry_TCPSocketServer";
    ​
    class SocketInfo {
      message: ArrayBuffer = new ArrayBuffer(1);
      remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
    }
    ​
    export class TCPSocketServerUtils {
      info: InfoObject//传参对象
      tcpServer:socket.TCPSocketServer;//TCP链接服务端实例
      clientRef?: socket.TCPSocketConnection;//TCP链接对象
    ​
      constructor(info: InfoObject) {
        // 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。
        this.tcpServer = socket.constructTCPSocketServerInstance();
        this.info = info
      }
    ​
      init() {
        let ipAddress: socket.NetAddress = {} as socket.NetAddress;
        ipAddress.address = "127.0.0.1";//服务端本机IP
        ipAddress.port = 8088;//服务端本地端口号
    ​
        // 绑定本地IP地址和端口,进行监听
        this.tcpServer.listen(ipAddress).then(() => {
          printLog(TAG, "服务端监听本地IP地址和端口成功");
        }).catch((err: BusinessError) => {
          printLog(TAG, '服务端监听本地IP地址和端口失败');
        });
        // 订阅TCPSocketServer的connect事件
        this.tcpServer.on("connect", (client: socket.TCPSocketConnection) => {
          this.clientRef = client;
          // 订阅TCPSocketConnection相关的事件
          client.on("close", () => {
            printLog(TAG, "TCPSocketConnection关闭");
          });
          client.on("message", (value: SocketInfo) => {
            printLog(TAG,"服务端TCPSocketConnection成功接收到消息")
            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));
            }
            printLog(TAG, "服务端 received message--:" + str);//消息内容
            printLog(TAG, "服务端 received address--:" + value.remoteInfo.address);//绑定的IP地址。
            printLog(TAG, "服务端 received family--:" + value.remoteInfo.family);//网络协议类型。选项包括:IPv4、IPv6。
            printLog(TAG, "服务端 received port--:" + value.remoteInfo.port);//端口号。取值范围是0 ~ 65535。
            printLog(TAG, "服务端 received size--:" + value.remoteInfo.size);//服务器响应消息的长度,以字节为单位。
    ​
            this.info.messageNumber++
            this.info.receiveMsg = str
            this.info.ipAddress = value.remoteInfo.address
            this.info.protocolType = value.remoteInfo.family
            this.info.portNumber = value.remoteInfo.port
            this.info.sizeMsg = value.remoteInfo.size
          });
        });
    ​
      }
    ​
      // 向客户端发送数据
      sendMsg() {
        let tcpSendOptions: socket.TCPSendOptions = {} as socket.TCPSendOptions;
        tcpSendOptions.data = 'this data is from server';
        this.clientRef?.send(tcpSendOptions).then(() => {
          printLog(TAG, '服务端向客户端发送数据成功');
        }).catch((err: Object) => {
          printLog(TAG,`服务端向客户端发送数据失败,info = ${JSON.stringify(err)}`);
        });
      }
    ​
      // 关闭与客户端的连接
      closeClient(){
        this.clientRef?.close().then(() => {
          printLog(TAG, '服务端主动关闭与客户端的链接,成功');
        }).catch((err: BusinessError) => {
          printLog(TAG, '服务端主动关闭与客户端的链接,失败');
        });
      }
    ​
      cancelEventSub(){
        // 取消TCPSocketConnection相关的事件订阅
        setTimeout(() => {
          this.clientRef?.off("message");
          this.clientRef?.off("close");
        }, 1 * 1000);
    ​
        // 取消TCPSocketServer相关的事件订阅
        setTimeout(() => {
          this.tcpServer.off("connect");
        }, 2 * 1000);
      }
    }
    ​
    function printLog(tag: string,info: string){
      hilog.info(0xff00,tag,info)
    }
感谢各位的热心支持,我这边在同事的帮助下已经顺利解决了。经过测试,证明是可以在两个模拟器上借助TCP 连接,实现双端通信的。操作步骤及完整代码,将在晚些时候发出来,供大家参考讨论。

要是模拟器有VMWare的那种“虚拟网络编辑器”就好了。

cke_301944.png

有人有真机可以测试一下,真机在同一个局域网内,我觉得TCP通讯应该没问题。

以下为测试代码:

需要修改代码中的服务端和客户端的IP地址为你的模拟器上设置的静态或者DHCP自动分配的IP。

一个模拟器点“开启Server”后;另一个模拟器点“开启Client”,接着点“连接服务端”,这儿就报error信息了。

import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
import { connection } from '@kit.NetworkKit';

class SocketInfo { message: ArrayBuffer = new ArrayBuffer(1); remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; }

// 构造单例对象 export class GlobalContext { public netList: connection.NetHandle[] = []; public netHandle: connection.NetHandle|null = null; private constructor() {} private static instance: GlobalContext; private _objects = new Map<string, Object>();

public static getContext(): GlobalContext { if (!GlobalContext.instance) { GlobalContext.instance = new GlobalContext(); } return GlobalContext.instance; }

getObject(value: string): Object | undefined { return this._objects.get(value); }

setObject(key: string, objectClass: Object): void { this._objects.set(key, objectClass); } }

@Entry @Component struct Index { @State netInfo: string = ‘网络信息’; @State message: string = ‘当前模式:?’; @State receivedMsg: string = ‘收到的消息’; @State sentMsg: string = ‘发送的消息’; mode: number = -1; //当前模式 0为服务端 1 为客户端 ///服务端///// tcpServer?: socket.TCPSocketServer; ///客户端///// tcpClient?: socket.TCPSocket;

onSentMsgChanged(value: string) { this.sentMsg = value; }

onGetNetworkInfo(){ // 调用getDefaultNet方法,获取默认的数据网络(NetHandle) connection.getDefaultNet().then((data:connection.NetHandle) => { if (data) { console.info("getDefaultNet get data: " + JSON.stringify(data)); GlobalContext.getContext().netHandle = data; // 获取netHandle对应网络的能力信息。能力信息包含了网络类型、网络具体能力等网络信息 connection.getNetCapabilities(GlobalContext.getContext().netHandle).then((data: connection.NetCapabilities) => { console.info("getNetCapabilities get data: " + JSON.stringify(data));

      <span class="hljs-comment"><span class="hljs-comment">// 获取网络类型(bearerTypes)</span></span>
      <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> bearerTypes: Set&lt;number&gt; = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> Set(data.bearerTypes);
      <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> bearerTypesNum = <span class="hljs-built_in"><span class="hljs-built_in">Array</span></span>.from(bearerTypes.values());
      <span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> item of bearerTypesNum) {
        <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">0</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 蜂窝网</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"BEARER_CELLULAR"</span></span>));
        } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">1</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// Wi-Fi网络</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"BEARER_WIFI"</span></span>));
        } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">3</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 以太网网络</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"BEARER_ETHERNET"</span></span>));
        }
      }

      <span class="hljs-comment"><span class="hljs-comment">// 获取网络具体能力(networkCap)</span></span>
      <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> itemNumber : Set&lt;number&gt; = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> Set(data.networkCap);
      <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> dataNumber = <span class="hljs-built_in"><span class="hljs-built_in">Array</span></span>.from(itemNumber.values());
      <span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> item of dataNumber) {
        <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">0</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 表示网络可以访问运营商的MMSC(Multimedia Message Service,多媒体短信服务)发送和接收彩信</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"NET_CAPABILITY_MMS"</span></span>));
        } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">11</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 表示网络流量未被计费</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"NET_CAPABILITY_NOT_METERED"</span></span>));
        } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">12</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 表示该网络应具有访问Internet的能力,该能力由网络提供者设置</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"NET_CAPABILITY_INTERNET"</span></span>));
        } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">15</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 表示网络不使用VPN(Virtual Private Network,虚拟专用网络)</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"NET_CAPABILITY_NOT_VPN"</span></span>));
        } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (item == <span class="hljs-number"><span class="hljs-number">16</span></span>) {
          <span class="hljs-comment"><span class="hljs-comment">// 表示该网络访问Internet的能力被网络管理成功验证,该能力由网络管理模块设置</span></span>
          console.log(<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(<span class="hljs-string"><span class="hljs-string">"NET_CAPABILITY_VALIDATED"</span></span>));
        }
      }
    })
  }
})

<span class="hljs-comment"><span class="hljs-comment">// 获取netHandle对应网络的连接信息。连接信息包含了链路信息、路由信息等</span></span>
connection.getConnectionProperties(GlobalContext.getContext().netHandle).then((data: connection.ConnectionProperties) =&gt; {
  console.info(<span class="hljs-string"><span class="hljs-string">"getConnectionProperties get data: "</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data));
})

<span class="hljs-comment"><span class="hljs-comment">// 调用getAllNets,获取所有处于连接状态的网络列表(Array&lt;NetHandle&gt;)</span></span>
connection.getAllNets().then((data: connection.NetHandle[]) =&gt; {
  console.info(<span class="hljs-string"><span class="hljs-string">"getAllNets get data: "</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data));
  <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (data) {
    GlobalContext.getContext().netList = data;

    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> itemNumber : Set&lt;connection.NetHandle&gt; = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> Set(GlobalContext.getContext().netList);
    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> dataNumber = <span class="hljs-built_in"><span class="hljs-built_in">Array</span></span>.from(itemNumber.values());
    <span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> item of dataNumber) {
      <span class="hljs-comment"><span class="hljs-comment">// 循环获取网络列表每个netHandle对应网络的能力信息</span></span>
      connection.getNetCapabilities(item).then((data: connection.NetCapabilities) =&gt; {
        console.info(<span class="hljs-string"><span class="hljs-string">"getNetCapabilities get data: "</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data));
      })

      <span class="hljs-comment"><span class="hljs-comment">// 循环获取网络列表每个netHandle对应的网络的连接信息</span></span>
      connection.getConnectionProperties(item).then((data: connection.ConnectionProperties) =&gt; {
        console.info(<span class="hljs-string"><span class="hljs-string">"getConnectionProperties get data: "</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data));
      })
    }
  }
})

}//end onGetNetworkInfo

onEnableServerClicked() { this.message = “当前是TCP服务端” this.mode = 0; // 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。 this.tcpServer = socket.constructTCPSocketServerInstance(); // 绑定本地IP地址和端口,进行监听

<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> ipAddress: socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = <span class="hljs-string"><span class="hljs-string">"192.168.76.10"</span></span>;
ipAddress.port = <span class="hljs-number"><span class="hljs-number">5678</span></span>;
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpServer.listen(ipAddress).then(() =&gt; {
  console.log(<span class="hljs-string"><span class="hljs-string">'listen success'</span></span>);
  promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"监听成功!"</span></span>, duration: <span class="hljs-number"><span class="hljs-number">2000</span></span> })
}).catch((err: BusinessError) =&gt; {
  console.log(<span class="hljs-string"><span class="hljs-string">'listen fail'</span></span>);
  promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"监听失败!"</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err), duration: <span class="hljs-number"><span class="hljs-number">5000</span></span> })
});

<span class="hljs-comment"><span class="hljs-comment">// 订阅TCPSocketServer的connect事件</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpServer.on(<span class="hljs-string"><span class="hljs-string">"connect"</span></span>, (client: socket.TCPSocketConnection) =&gt; {
  <span class="hljs-comment"><span class="hljs-comment">// 订阅TCPSocketConnection相关的事件</span></span>
  client.on(<span class="hljs-string"><span class="hljs-string">"close"</span></span>, () =&gt; {
    console.log(<span class="hljs-string"><span class="hljs-string">"on close success"</span></span>);
  });
  client.on(<span class="hljs-string"><span class="hljs-string">"message"</span></span>, (value: SocketInfo) =&gt; {
    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> buffer = value.message;
    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> dataView = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-built_in"><span class="hljs-built_in">DataView</span></span>(buffer);
    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> str = <span class="hljs-string"><span class="hljs-string">""</span></span>;
    <span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> i = <span class="hljs-number"><span class="hljs-number">0</span></span>; i &lt; dataView.byteLength; ++i) {
      str += <span class="hljs-built_in"><span class="hljs-built_in">String</span></span>.fromCharCode(dataView.getUint8(i));
    }
    <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.receivedMsg = str;
    console.log(<span class="hljs-string"><span class="hljs-string">"received message--:"</span></span> + str);
    console.log(<span class="hljs-string"><span class="hljs-string">"received address--:"</span></span> + value.remoteInfo.address);
    console.log(<span class="hljs-string"><span class="hljs-string">"received family--:"</span></span> + value.remoteInfo.family);
    console.log(<span class="hljs-string"><span class="hljs-string">"received port--:"</span></span> + value.remoteInfo.port);
    console.log(<span class="hljs-string"><span class="hljs-string">"received size--:"</span></span> + value.remoteInfo.size);
  });

  <span class="hljs-comment"><span class="hljs-comment">// 向客户端发送数据</span></span>
  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> tcpSendOptions: socket.TCPSendOptions = {} as socket.TCPSendOptions;
  tcpSendOptions.data = <span class="hljs-string"><span class="hljs-string">'ServerReceived:'</span></span> + <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.receivedMsg;
  client.send(tcpSendOptions).then(() =&gt; {
    console.log(<span class="hljs-string"><span class="hljs-string">'send success'</span></span>);
    promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"发送成功!"</span></span>, duration: <span class="hljs-number"><span class="hljs-number">2000</span></span> })
  }).catch((err: <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>) =&gt; {
    console.error(<span class="hljs-string"><span class="hljs-string">'send fail: '</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err));
    promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"发送失败!"</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err), duration: <span class="hljs-number"><span class="hljs-number">5000</span></span> })
  });

});

} //end onEnableServerClicked

onEnableClientClicked() { this.message = “当前是TCP客户端” this.mode = 1; // 创建一个TCPSocket连接,返回一个TCPSocket对象。 this.tcpClient = socket.constructTCPSocketInstance();

<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient.on(<span class="hljs-string"><span class="hljs-string">'message'</span></span>, (value: SocketInfo) =&gt; {
  console.log(<span class="hljs-string"><span class="hljs-string">"on message"</span></span>);
  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> buffer = value.message;
  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> dataView = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-built_in"><span class="hljs-built_in">DataView</span></span>(buffer);
  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> str = <span class="hljs-string"><span class="hljs-string">""</span></span>;
  <span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> i = <span class="hljs-number"><span class="hljs-number">0</span></span>; i &lt; dataView.byteLength; ++i) {
    str += <span class="hljs-built_in"><span class="hljs-built_in">String</span></span>.fromCharCode(dataView.getUint8(i));
  }
  <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.receivedMsg = str;
  console.log(<span class="hljs-string"><span class="hljs-string">"on connect received:"</span></span> + str);
});

<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient.on(<span class="hljs-string"><span class="hljs-string">'connect'</span></span>, () =&gt; {
  console.log(<span class="hljs-string"><span class="hljs-string">"on connect"</span></span>);
});
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient.on(<span class="hljs-string"><span class="hljs-string">'close'</span></span>, () =&gt; {
  console.log(<span class="hljs-string"><span class="hljs-string">"on close"</span></span>);
});

<span class="hljs-comment"><span class="hljs-comment">// 绑定本地IP地址和端口。</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> ipAddress: socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = <span class="hljs-string"><span class="hljs-string">"192.168.76.9"</span></span>;
ipAddress.port = <span class="hljs-number"><span class="hljs-number">1234</span></span>;
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient.bind(ipAddress, (err: BusinessError) =&gt; {
  <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (err) {
    console.log(<span class="hljs-string"><span class="hljs-string">'bind fail'</span></span>);
    promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"绑定失败!"</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err), duration: <span class="hljs-number"><span class="hljs-number">5000</span></span> })
    <span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
  }
  console.log(<span class="hljs-string"><span class="hljs-string">'bind success'</span></span>);
  promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"绑定成功!"</span></span>, duration: <span class="hljs-number"><span class="hljs-number">2000</span></span> })
});

} //end onEnableClientClicked

onClientConnectBtnClicked() { // 连接到指定的IP地址和端口。 let ipAddress: socket.NetAddress = {} as socket.NetAddress; ipAddress.address = “192.168.76.10”; ipAddress.port = 5678;

<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> tcpConnect: socket.TCPConnectOptions = {} as socket.TCPConnectOptions;
tcpConnect.address = ipAddress;
tcpConnect.timeout = <span class="hljs-number"><span class="hljs-number">6000</span></span>;

<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient) {
  <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient.connect(tcpConnect).then(() =&gt; {
    console.log(<span class="hljs-string"><span class="hljs-string">'connect success'</span></span>);
    promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"连接成功!"</span></span>, duration: <span class="hljs-number"><span class="hljs-number">2000</span></span> })
  }).catch((err: BusinessError) =&gt; {
    console.log(<span class="hljs-string"><span class="hljs-string">'connect fail'</span></span>);
    promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"连接失败!"</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err), duration: <span class="hljs-number"><span class="hljs-number">5000</span></span> })
  });
}

}

onSendClicked() { if (this.mode == 0) { //服务器端发送

}

<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.mode == <span class="hljs-number"><span class="hljs-number">1</span></span>) {
  <span class="hljs-comment"><span class="hljs-comment">//客户端发送</span></span>
  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> tcpSendOptions: socket.TCPSendOptions = {
    data: <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.sentMsg
  };
  <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient) {
    <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpClient.send(tcpSendOptions).then(() =&gt; {
      console.log(<span class="hljs-string"><span class="hljs-string">'send success'</span></span>);
      promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"发送成功!"</span></span>, duration: <span class="hljs-number"><span class="hljs-number">2000</span></span> })
    }).catch((err: BusinessError) =&gt; {
      console.log(<span class="hljs-string"><span class="hljs-string">'send fail'</span></span>);
      promptAction.showToast({ message: <span class="hljs-string"><span class="hljs-string">"发送失败!"</span></span> + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err), duration: <span class="hljs-number"><span class="hljs-number">5000</span></span> })
    });
  }
}

}

build() { Column() { Row() { Text(this.netInfo).height(“56vp”) }

  Row() {
    Button(<span class="hljs-string"><span class="hljs-string">"获取网络信息"</span></span>)
      .width(<span class="hljs-string"><span class="hljs-string">'50%'</span></span>)
      .height(<span class="hljs-string"><span class="hljs-string">'26vp'</span></span>)
      .onClick(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onGetNetworkInfo.bind(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>))
  }.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
  .justifyContent(FlexAlign.Center)


  Row() {
    Text(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.message).height(<span class="hljs-string"><span class="hljs-string">"26vp"</span></span>)
  }

  Row() {
    Button(<span class="hljs-string"><span class="hljs-string">"开启Server"</span></span>)
      .width(<span class="hljs-string"><span class="hljs-string">'40%'</span></span>)
      .height(<span class="hljs-string"><span class="hljs-string">'26vp'</span></span>)
      .onClick(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onEnableServerClicked.bind(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>))
    Button(<span class="hljs-string"><span class="hljs-string">"开启Client"</span></span>)
      .width(<span class="hljs-string"><span class="hljs-string">'40%'</span></span>)
      .height(<span class="hljs-string"><span class="hljs-string">'26vp'</span></span>)
      .onClick(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onEnableClientClicked.bind(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>))
  }.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
  .justifyContent(FlexAlign.SpaceEvenly)

  Row() {
    Button(<span class="hljs-string"><span class="hljs-string">"连接服务端"</span></span>)
      .width(<span class="hljs-string"><span class="hljs-string">'50%'</span></span>)
      .height(<span class="hljs-string"><span class="hljs-string">'26vp'</span></span>)
      .onClick(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onClientConnectBtnClicked.bind(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>))
  }.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
  .justifyContent(FlexAlign.Center)

  Row() {
    Text(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.receivedMsg).height(<span class="hljs-string"><span class="hljs-string">"66vp"</span></span>)
  }

  TextInput({ placeholder: <span class="hljs-string"><span class="hljs-string">"输入要发送的消息"</span></span> })
    .width(<span class="hljs-string"><span class="hljs-string">"90%"</span></span>)
    .height(<span class="hljs-string"><span class="hljs-string">"36vp"</span></span>)
    .onChange((value: string) =&gt; <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onSentMsgChanged(value))

  Row() {
    Button(<span class="hljs-string"><span class="hljs-string">"发送消息"</span></span>)
      .width(<span class="hljs-string"><span class="hljs-string">'40%'</span></span>)
      .height(<span class="hljs-string"><span class="hljs-string">'26vp'</span></span>)
      .onClick(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onSendClicked.bind(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>))
  }.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
  .justifyContent(FlexAlign.Center)

}
.height(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)

} //end build() }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

记得添加权限:

cke_23226.png

测试过了,模拟器上搞不定。拿不到真实的模拟器IP地址。设置静态IP在同一个网段内也不通。

cke_1345.png

开启WLAN并连接VirtWifi后进去,IP选择“静态”后自行配置个IP,然后重启两个模拟器,就可以看到IP地址更新了。

最后你再写TCP代码试试。如果TCP能通请回复一下,我也挺想知道结果。

静态IP修改:

cke_3562.png

重启模拟器后:

cke_4466.png

在HarmonyOS(鸿蒙)的开发者环境中,要实现两个模拟器之间的网络互联,通常涉及几个关键步骤:

  1. 确保模拟器网络连接:首先,确保每个模拟器都能独立访问网络,这通常是通过模拟器设置中的网络配置来完成的。检查模拟器是否配置了有效的网络代理(如果有需要)或直接连接到宿主机的网络。

  2. 使用桥接网络模式:在模拟器设置中,尝试将网络模式设置为桥接模式(如果可用)。桥接模式允许模拟器直接连接到宿主机的物理网络,从而可能更容易实现模拟器间的直接通信。

  3. IP地址分配:确保两个模拟器被分配了不同的IP地址,并且它们位于同一子网内,以便能够相互访问。

  4. 防火墙和安全组设置:检查宿主机的防火墙或任何可能影响网络通信的安全组设置,确保没有阻止模拟器间的通信。

  5. 使用网络工具测试:使用如ping或telnet等网络工具来测试模拟器之间的网络连通性。

  6. 模拟器内网络配置:如果模拟器运行的是完整的操作系统,还可能需要在模拟器内部进行网络配置,如设置静态IP、DNS等。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html 。这将有助于获取更具体的技术支持和解决方案。

回到顶部