鸿蒙模拟器模拟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端口映射
-
以管理员身份运行 命令提示符
-
电脑IP和本地模拟器IP端口映射
在命令行输入以下代码,其中connectaddress=127.0.0.1 connectport=8000必须一致
当有服务访问"你电脑的IP:8888"时,操作系统会自动映射到“127.0.0.1:8000”
netsh interface portproxy add v4tov4 listenaddress=你的电脑的IP地址 listenport=8888 connectaddress=127.0.0.1 connectport=8000
显示映射结果
netsh interface portproxy show v4tov4
设置端口转发
首先启动本地模拟器
在进行端口转发前,一定要先启动本地模拟器,即 本地模拟器每次重启都需要重新设备端口转发
接下来需要配置鸿蒙模拟器端口转发,使用HDC命令操作,需要用到hdc.exe
文件,该文件在OpenHarmony SDK目录下的\toolchains
目录内部找到(每个人的路径不同),需要记住该目录。例如我的电脑上hdc.exe的路径:
进入toolchains目录,在命令行执行以下命令进行端口转发:
注意:本地模拟器每次重启都需要重新进行端口转发
hdc.exe -t 127.0.0.1:5555 fport tcp:8000 tcp:8000
执行以上命令,得到如下结果
最后将项目部署到模拟器上,启动服务端便可以和TCP客户端连接并且通信了!!!