鸿蒙本地模拟器 模拟TCP服务端的过程

鸿蒙模拟器模拟TCP服务端的过程涉及几个关键步骤,主要包括创建TCPSocketServer实例、绑定IP地址和端口、监听连接请求、接收和发送数据以及处理连接事件。以下是详细的模拟过程:

**1.创建TCPSocketServer实例:**首先,需要导入鸿蒙的socket模块,并创建一个TCPSocketServer对象。这个对象将用于管理TCP连接。

**2.绑定IP地址和端口:**通过调用listen()方法,将TCPSocketServer实例绑定到本地IP地址和端口上。这样,服务端就可以监听指定端口上的连接请求。

**3.监听连接请求:**服务端通过订阅TCPSocketServer的connect事件来监听客户端的连接请求。当客户端尝试连接时,服务端会接收到一个连接事件。

**4.接收和发送数据:**一旦客户端和服务端建立连接,服务端会返回一个TCPSocketConnection对象,用于与客户端进行数据通信。服务端可以通过订阅TCPSocketConnection的message事件来接收客户端发送的数据,并通过调用send()方法来向客户端发送数据。

**5.处理连接事件:**服务端还需要处理其他事件,如close和error,以管理连接的生命周期和错误处理。

**6.UI效果展示:**在模拟器上,服务端接收到的控制命令可以通过UI界面展示。例如,当客户端发送一个"开灯"命令时,服务端的UI界面会相应地更新灯的状态,或者通过改变颜色或显示图片来模拟灯的开启。

**7.端口映射和转发:**为了使服务端能够在模拟器上正确地与外部客户端通信,可能需要进行端口映射和转发。这通常通过命令行工具如netsh或鸿蒙的HDC命令来实现,将模拟器的端口映射到主机的端口上。

上诉步骤中,1-6的步骤可以根据开发者文档的TCP服务端实现操作,并且直接通过本地模拟器运行项目即可。例如以下案例:

复制代码
/**
 * 1.导入 socket 模块
 */
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 2.创建 TCPSocketServer
 * 创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象。
 */
let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance();

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

@Entry
@Component
struct Index {
  @State showDatas: string[] = [] //用于接收客服端发送的消息
  @State serverLocalIp: string = '127.0.0.1'
  @State serverPort: number = 8000
  @State serverData:string = '服务端发送的信息'
  private connectState: boolean = false
  private tcpSocketConnection ?: socket.TCPSocketConnection

  async listenServer(serverIp: string, serverPort: number) {
    let ipAddress: socket.NetAddress = {
      address: serverIp,
      port: serverPort,
    }
    // 绑定IP:Port、监听并启动服务,接收客户端的连接请求
    tcpServer.listen(ipAddress).then(() => {
      console.info('===listen success===');
      tcpServer.on("connect", (tcpConnection: socket.TCPSocketConnection) => {
        console.info("===connect success====")
        this.connectState = true
        this.tcpSocketConnection = tcpConnection

        tcpConnection.on("message", (data: SocketInfo) => {
          console.info("====receive message====")
          let buffer = data.message;
          let dataView = new DataView(buffer);
          let messageData = "";
          for (let i = 0; i < dataView.byteLength; ++i) {
            messageData += String.fromCharCode(dataView.getUint8(i));
          }
          this.showDatas.push('客户端:' + messageData)
        });
        // 订阅TCPSocketConnection相关的事件
        tcpConnection.on("close", () => {
          console.info("===断开连接===");
        });
      })
    }).catch((err: BusinessError) => {
      console.info('listen fail');
    });}

  async sendData(message: string) {
    if (this.connectState) { //连接成功才可发送数据
      // 服务端给连接的客户端发送信息
      let tcpSendOptions: socket.TCPSendOptions = {} as socket.TCPSendOptions;
      tcpSendOptions.data = message
      this.tcpSocketConnection?.send(tcpSendOptions).then(() => {
        console.info('===send success===');
        this.showDatas.push('服务端:' + tcpSendOptions.data)
      })
    }
  }

  build() {
    Column({ space: 5 }) {
      Text('TCP的服务端实现')
        .fontSize(30)

      Row({ space: 5 }) {
        Text('服务端ip:')
          .width(110)
          .fontSize(20)
          .textAlign(TextAlign.End)

        TextInput({ placeholder: this.serverLocalIp })
          .fontSize(20)
          .width('60%')
          .onChange((value) => {
            this.serverLocalIp = value
          })
      }

      Row({ space: 5 }) {
        Text('服务端port:')
          .width(110)
          .fontSize(20)
          .textAlign(TextAlign.End)
        TextInput({ placeholder: this.serverPort.toString() })
          .fontSize(20)
          .width('60%')
          .type(InputType.Number)
          .onChange((value) => {
            this.serverPort = parseInt(value)
          })
      }

      Button('服务端启动并监听连接')
        .fontSize(25)
        .onClick(() => {
          this.listenServer(this.serverLocalIp, this.serverPort)
        })
      TextInput({ placeholder: this.serverData })
        .fontSize(20)
        .width('90%')
        .height(50)
        .onChange((value) => {
          this.serverData = value
        })
      Button('发送消息') //监听连接状态
        .fontSize(25)
        .onClick(()=>{
          this.sendData(this.serverData)
        })

      List(){
        ListItem(){
          Text('服务端消息展示:')
        }
        ForEach(this.showDatas, (item: string) => {
          ListItem(){
            Text(item)
              .fontSize(20)
          }
        })
      }.width('95%')
      .layoutWeight(1)
    }
  }
}

以上代码的UI效果:

因为需要使用网络,需要开通网络权限:

本地模拟器模拟TCP服务端的必备操作

IP端口映射

  1. 以管理员身份运行 命令提示符

  2. 电脑IP和本地模拟器IP端口映射

    在命令行输入以下代码,其中connectaddress=127.0.0.1 connectport=8000 必须一致

    当有服务访问"你电脑的IP:8888 "时,操作系统会自动映射到"127.0.0.1:8000"

javascript 复制代码
netsh interface portproxy add v4tov4 listenaddress=你的电脑的IP地址 listenport=8888 connectaddress=127.0.0.1 connectport=8000

显示映射结果

javascript 复制代码
netsh interface portproxy show v4tov4

设置端口转发

首先启动本地模拟器
在进行端口转发前,一定要先启动本地模拟器 ,即 本地模拟器每次重启都需要重新设备端口转发

接下来需要配置鸿蒙模拟器端口转发,使用HDC命令操作,需要用到hdc.exe文件 ,该文件在OpenHarmony SDK目录下的\toolchains目录内部找到(每个人的路径不同 ),需要记住该目录。例如我的电脑上hdc.exe的路径:

进入toolchains目录,在命令行执行以下命令进行端口转发:

注意:本地模拟器每次重启都需要重新进行端口转发

javascript 复制代码
hdc.exe -t 127.0.0.1:5555 fport tcp:8000 tcp:8000

执行以上命令,得到如下结果

最后将项目部署到模拟器上,启动服务端便可以和TCP客户端连接并且通信了!!!

相关推荐
天夏已微凉4 分钟前
OpenHarmony系统HDF驱动开发介绍(补充)
驱动开发·音视频·harmonyos
虹科汽车电子24 分钟前
虹科技术 | ANDi软件应用:SOME/IP协议如何重塑车载通信架构?
tcp/ip·车载以太网·vlan配置·增强型以太网交换机
z人间防沉迷k3 小时前
TCP核心机制
网络·网络协议·tcp/ip·http
像风一样_5 小时前
TCP首部格式及三次握手四次挥手
网络·网络协议·tcp/ip
特立独行的猫a6 小时前
HarmonyOS 【诗韵悠然】AI古诗词赏析APP开发实战从零到一系列(一、开篇,项目介绍)
人工智能·华为·harmonyos·古诗词
幽蓝计划11 小时前
鸿蒙跨平台开发教程之Uniapp布局基础
harmonyos
周胡杰11 小时前
鸿蒙接入flutter环境变量配置windows-命令行或者手动配置-到项目的创建-运行demo项目
javascript·windows·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
嵌入式在学无敌大神12 小时前
IP协议、以太网包头及UNIX域套接字
网络·tcp/ip·unix
2501_9159090612 小时前
iOS App 安全性探索:源码保护、混淆方案与逆向防护日常
websocket·网络协议·tcp/ip·http·网络安全·https·udp
半青年13 小时前
华为鸿蒙电脑能否作为开发机?开发非鸿蒙应用?
ide·华为·编辑器·电脑·idea·harmonyos·visual studio