文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
开源 Arkts 鸿蒙应用 开发(一)工程文件分析-CSDN博客
开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-CSDN博客
开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-CSDN博客
开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-CSDN博客
开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-CSDN博客
开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储-CSDN博客
开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库-CSDN博客
开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机-CSDN博客
开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端-CSDN博客
开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输-CSDN博客
推荐链接:
开源 java android app 开发(一)开发环境的搭建-CSDN博客
开源 java android app 开发(二)工程文件结构-CSDN博客
开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客
开源 java android app 开发(四)GUI界面重要组件-CSDN博客
开源 java android app 开发(五)文件和数据库存储-CSDN博客
开源 java android app 开发(六)多媒体使用-CSDN博客
开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客
开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客
开源 java android app 开发(九)后台之线程和服务-CSDN博客
开源 java android app 开发(十)广播机制-CSDN博客
开源 java android app 开发(十一)调试、发布-CSDN博客
开源 java android app 开发(十二)封库.aar-CSDN博客
推荐链接:
开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客
开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客
开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客
开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客
开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客
本章内容主要是演示鸿蒙的tcp客户端的通讯:
实现TCP客户端功能,可以连接指定IP和端口的服务器。支持发送和接收文本消息,显示连接状态和通信历史。
新建DevEco的工程,选择Empty Ability,只需要修改module.json5,和Index.ets文件,就可以实现TCP客户端的APP。
一、设置权限,修改module.json5文件。
文件位置
module.json5代码
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
二、Index.ets的代码
// MainAbility.ets
import socket from '@ohos.net.socket';
import common from '@ohos.app.ability.common';
import promptAction from '@ohos.promptAction';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct TcpClientPage {
@State serverIp: string = '192.168.3.146'; // 默认服务器IP
@State serverPort: string = '1000'; // 默认端口
@State message: string = ''; // 要发送的消息
@State receivedData: string = ''; // 接收到的数据
@State isConnected: boolean = false; // 连接状态
private tcpSocket: socket.TCPSocket = socket.constructTCPSocketInstance();
private context = getContext(this) as common.UIAbilityContext;
// 初始化TCP套接字
aboutToAppear() {
this.tcpSocket = socket.constructTCPSocketInstance();
// 设置TCP连接参数
let tcpOptions: socket.TCPConnectOptions = {
address: {
address: this.serverIp,
port: parseInt(this.serverPort),
family: 1 // 1表示IPv4
},
timeout: 5000 // 连接超时时间5秒
};
// 监听接收数据
this.tcpSocket.on('message', (messageInfo: socket.SocketMessageInfo) => {
console.info('Received message');
// 从 SocketMessageInfo 中获取 ArrayBuffer
const buffer = messageInfo.message; // message 是 ArrayBuffer 类型
const data = this.arrayBufferToString(buffer);
this.receivedData += `[接收] ${new Date().toLocaleTimeString()}: ${data}\n`;
});
// 监听连接关闭
this.tcpSocket.on('close', () => {
console.info('Connection closed');
this.isConnected = false;
promptAction.showToast({ message: '连接已关闭', duration: 2000 });
});
// 监听错误事件
this.tcpSocket.on('error', (err) => {
console.error('Socket error: ' + JSON.stringify(err));
promptAction.showToast({ message: '发生错误: ' + JSON.stringify(err), duration: 3000 });
this.isConnected = false;
});
}
private arrayBufferToString(buffer: ArrayBuffer): string {
const uint8Array = new Uint8Array(buffer);
let str = '';
for (let i = 0; i < uint8Array.length; i++) {
str += String.fromCharCode(uint8Array[i]);
}
return str;
}
// 字符串转ArrayBuffer
private stringToArrayBuffer(str: string): ArrayBuffer {
let buf = new ArrayBuffer(str.length);
let bufView = new Uint8Array(buf);
for (let i = 0; i < str.length; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
// 连接/断开服务器
private toggleConnection() {
if (this.isConnected) {
this.disconnect();
} else {
this.connect();
}
}
// 连接到服务器
private async connect() {
try {
let tcpOptions: socket.TCPConnectOptions = {
address: {
address: this.serverIp,
port: parseInt(this.serverPort),
family: 1
},
timeout: 5000
};
await this.tcpSocket.connect(tcpOptions);
this.isConnected = true;
promptAction.showToast({ message: '连接成功', duration: 2000 });
// 开始接收数据
this.tcpSocket.getState().then(state => {
console.info('Socket state: ' + JSON.stringify(state));
});
} catch (err) {
console.error('Connect failed: ' + JSON.stringify(err));
promptAction.showToast({ message: '连接失败: ' + JSON.stringify(err), duration: 3000 });
this.isConnected = false;
}
}
// 断开连接
private disconnect() {
try {
this.tcpSocket.close();
this.isConnected = false;
promptAction.showToast({ message: '已断开连接', duration: 2000 });
} catch (err) {
console.error('Disconnect failed: ' + JSON.stringify(err));
promptAction.showToast({ message: '断开连接失败: ' + JSON.stringify(err), duration: 3000 });
}
}
private sendMessage() {
if (!this.isConnected) {
promptAction.showToast({ message: '请先连接到服务器', duration: 2000 });
return;
}
if (!this.message.trim()) {
promptAction.showToast({ message: '消息不能为空', duration: 2000 });
return;
}
try {
const buffer = this.stringToArrayBuffer(this.message);
this.tcpSocket.send({ data: buffer })
.then(() => {
this.receivedData += `[发送] ${new Date().toLocaleTimeString()}: ${this.message}\n`;
this.message = '';
})
.catch((err: BusinessError) => {
console.error(`Send failed: code=${err.code}, message=${err.message}`);
promptAction.showToast({ message: `发送失败: ${err.message}`, duration: 3000 });
});
} catch (err) {
console.error(`Send error: code=${err.code}, message=${err.message}`);
promptAction.showToast({ message: `发送错误: ${err.message}`, duration: 3000 });
}
}
build() {
Column({ space: 10 }) {
// 标题
Text('TCP客户端')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 服务器地址输入
Row({ space: 10 }) {
Text('服务器IP:')
.fontSize(16)
.width(80)
TextInput({ text: this.serverIp })
.width('60%')
.onChange((value: string) => {
this.serverIp = value;
})
}.width('100%')
.justifyContent(FlexAlign.Start)
// 端口号输入
Row({ space: 10 }) {
Text('端口号:')
.fontSize(16)
.width(80)
TextInput({ text: this.serverPort })
.width('60%')
.onChange((value: string) => {
this.serverPort = value;
})
}.width('100%')
.justifyContent(FlexAlign.Start)
// 连接按钮
Button(this.isConnected ? '断开连接' : '连接')
.width('80%')
.height(40)
.backgroundColor(this.isConnected ? '#ff4d4f' : '#1890ff')
.onClick(() => {
this.toggleConnection();
})
// 消息输入框
TextInput({ placeholder: '输入要发送的消息', text: this.message })
.width('90%')
.height(60)
.margin({ top: 20 })
.onChange((value: string) => {
this.message = value;
})
// 发送按钮
Button('发送')
.width('80%')
.height(40)
.margin({ top: 10 })
.onClick(() => {
this.sendMessage();
})
// 消息显示区域
Scroll() {
Text(this.receivedData)
.width('90%')
.fontSize(14)
.textAlign(TextAlign.Start)
.padding(10)
.backgroundColor('#f5f5f5')
}
.width('100%')
.height(200)
.margin({ top: 20 })
.border({ width: 1, color: '#d9d9d9' })
}
.width('100%')
.height('100%')
.padding(20)
.justifyContent(FlexAlign.Start)
}
}
三、效果演示
3.1 首先搭建服务器端,这里使用了网络调试助手,设置ip和端口号,

3.2 APP的效果和设置
