DC娱乐网

鸿蒙TCP客户端代码拆解教程(小白也能看懂,直接复制可用)

鸿蒙TCP客户端代码拆解教程(小白也能看懂,直接复制可用)很多鸿蒙开发者都反馈,TCP通信这块是难点——要么连不上服务器

鸿蒙TCP客户端代码拆解教程(小白也能看懂,直接复制可用)

很多鸿蒙开发者都反馈,TCP通信这块是难点——要么连不上服务器,要么发不了消息,要么解析数据报错。今天就把这份可直接运行的鸿蒙TCP客户端代码,逐行拆解、加通俗注释,从依赖导入到界面布局,每一步都讲透,小白也能跟着学、跟着用,复制粘贴就能跑通!

先说明:这份代码是鸿蒙Stage模型下的TCP客户端,实现了「连接服务器、发送消息、接收响应、日志调试」四大核心功能,还加了Ping测试、回声测试、计算器功能(通过TCP发送计算指令,服务器返回结果),实用性拉满,不管是练手还是项目复用都合适。

第一步:先看整体结构(先有框架,再填细节)

整个代码分为5个核心部分,咱们一步步来,不跳步、不绕弯:

依赖导入:引入鸿蒙系统自带的TCP、工具、弹窗等API(不用自己写,直接导入就能用);接口定义:规范发送、接收的数据格式(避免乱码、解析失败,这是TCP通信的关键);组件状态:定义界面显示、连接状态、消息内容等变量(和界面联动,直观看到连接情况);核心方法:实现Socket初始化、连接/断开服务器、发送/接收消息等核心逻辑(重点中的重点);界面布局:用鸿蒙组件搭好操作界面(输入IP端口、发送消息、查看日志,可视化操作)。

第二步:逐段拆解代码(带通俗注释,复制即用)

每一段代码都加了「口语化注释」,不用懂复杂的底层原理,知道这段代码做什么、怎么改就行,重点地方标红提醒。

1. 依赖导入(必写,少一个都报错)

typescript// 导入鸿蒙TCP通信核心API(重点,实现TCP连接全靠它)import socket from '@ohos.net.socket';// 导入鸿蒙错误处理API(捕获连接、发送过程中的错误)import { BusinessError } from '@ohos.base';// 导入鸿蒙工具API(主要用于字符串和二进制数据的转换,避免乱码)import util from '@ohos.util';// 导入鸿蒙弹窗API(操作提示,比如连接成功、发送失败,用户能直观看到)import promptAction from '@ohos.promptAction';

重点提醒:这4个依赖是固定的,不用改,直接复制粘贴即可。如果报错,检查一下鸿蒙SDK版本(建议API 9及以上,Stage模型)。

2. 接口定义(关键!规范数据格式,避免解析失败)

TCP通信中,发送和接收的数据都是「字符串/二进制」,用接口定义格式,能避免发送乱码、接收后解析报错,这是很多新手踩坑的地方!

typescript// 定义「发送给服务器」的数据格式(客户端→服务器)// 不同功能对应不同type,服务器根据type判断要做什么interface MessageData {type: string; // 消息类型:echo(回声)、ping(心跳)、calculate(计算)content?: string; // 回声测试的消息内容(可选,只有type为echo时需要)operation?: string; // 计算操作(可选,add加、subtract减等,type为calculate时需要)a?: number; // 计算的第一个数字(可选,type为calculate时需要)b?: number; // 计算的第二个数字(可选,type为calculate时需要)}// 定义「服务器返回」的数据格式(服务器→客户端)// 客户端接收后,根据type判断怎么显示结果interface ResponseData {type: string; // 响应类型:echo_response(回声响应)、pong(心跳响应)等message?: string; // 提示消息(可选,比如连接成功提示)timestamp?: string; // 时间戳(可选,标记响应时间)original_message?: string; // 原始消息(可选,回声响应时,返回客户端发送的消息)result?: number | string; // 计算结果(可选,type为calculate_response时需要)status?: string; // 状态(可选,比如连接状态、计算状态)}

通俗理解:就像两个人聊天,要先说清楚「聊什么类型的话题」(type),再讲具体内容。比如客户端发type: 'ping',服务器就知道是心跳测试,返回type: 'pong'。

3. 组件状态定义(和界面联动,直观看到状态)

这些变量都是「响应式」的,值变了,界面上对应的显示也会跟着变(比如连接成功后,按钮从「连接服务器」变成「断开连接」)。

typescript@Entry // 标记当前组件是入口组件(整个APP的首页)@Component // 标记这是一个鸿蒙组件struct Index {// 服务器IP(默认值可修改,改成自己的服务器IP)@State serverIp: string = '192.168.212.99';// 服务器端口(默认8888,改成自己的服务器端口,范围1-65535)@State serverPort: string = '8888';// 连接状态(true=已连接,false=未连接)@State isConnected: boolean = false;// 要发送的消息(回声测试时,输入的内容)@State messageToSend: string = '';// 服务器返回的响应(原样显示,方便调试)@State responseMessage: string = '';// 计算功能的第一个数字(输入框绑定的值)@State aValue: string = '';// 计算功能的第二个数字(输入框绑定的值)@State bValue: string = '';// 计算结果(服务器返回后,显示在这里)@State calculationResult: string = '';// 调试日志(记录连接、发送、接收的全过程,方便找bug)@State logMessages: string[] = [];// 连接状态文本(未连接/连接中/已连接/已断开,显示在界面上)@State connectionStatus: string = '未连接';// TCP Socket实例(核心对象,所有TCP操作都靠它)private tcpSocket?: socket.TCPSocket;// 滚动器(日志、响应内容太多时,可滚动查看)private scroller: Scroller = new Scroller();

新手修改点:这里的serverIp和serverPort,改成自己的TCP服务器IP和端口(比如本地服务器IP是192.168.1.105,端口8888),否则连不上服务器。

4. 核心工具方法(封装复用,减少重复代码)

这3个方法是「工具类」,后面很多地方都会用到,封装起来不用重复写,新手重点理解功能,不用改代码。

(1)添加调试日志(记录全过程,找bug必备)

typescript// 添加调试日志,带时间戳,同时打印到控制台,还能区分错误日志// message:日志内容,isError:是否是错误日志(true=错误,false=正常)private addLog(message: string, isError: boolean = false): void {// 获取当前时间戳(格式:时:分:秒,方便查看时间)const timestamp: string = new Date().toLocaleTimeString();// 拼接日志内容(时间+消息)const logEntry = `${timestamp} - ${message}`;// 把新日志放到最前面(最新的日志显示在顶部,不用翻页)this.logMessages = [logEntry, ...this.logMessages];// 错误日志打印到控制台错误栏,正常日志打印到控制台信息栏if (isError) {console.error(message);} else {console.log(message);}}

作用:不管是连接成功、发送失败,还是收到消息,都会记录下来,在界面的「日志」标签页能看到,找bug时特别方便(比如连不上服务器,日志会显示失败原因)。

(2)二进制转字符串(避免乱码,关键一步)

typescript// 把服务器返回的二进制数据,转换成字符串(否则会显示乱码)// buffer:服务器返回的二进制数据private ab2str(buffer: ArrayBuffer): string {// 创建UTF-8解码器(鸿蒙自带,专门用于二进制转字符串)const decoder = new util.TextDecoder('utf-8');// 把二进制数据转换成Uint8Array格式(解码器需要这种格式)const uint8Array = new Uint8Array(buffer);// 解码成字符串,返回return decoder.decode(uint8Array);}

重点:TCP发送/接收的是二进制数据,如果直接显示,会是一堆乱码,这个方法就是把二进制转成我们能看懂的字符串。

(3)字符串转二进制(发送消息必备)

typescript// 把我们要发送的字符串,转换成二进制数据(TCP只能发送二进制)// str:要发送的字符串(比如回声消息、计算指令)private str2ab(str: string): ArrayBuffer {// 创建UTF-8编码器(和上面的解码器对应)const encoder = new util.TextEncoder();// 把字符串编码成Uint8Array格式const uint8Array = encoder.encode(str);// 转换成二进制缓冲区,返回return uint8Array.buffer;}

通俗理解:我们输入的是字符串(比如“你好”),但TCP不认识字符串,只能认识二进制,这个方法就是把“你好”转换成TCP能识别的二进制数据。

5. 核心业务方法(TCP通信的核心,重点拆解)

这部分是整个代码的灵魂,实现了TCP客户端的所有核心功能,每一个方法都讲透,新手能看懂、能修改。

(1)初始化Socket(连接服务器前,必须先做这一步)

typescript// 初始化TCP Socket实例,绑定消息接收、连接关闭、错误监听事件private initSocket(): void {try {this.addLog('正在初始化Socket...');// 创建TCP Socket实例(鸿蒙自带方法,直接调用)this.tcpSocket = socket.constructTCPSocketInstance();// 监听「消息接收」事件:服务器发送消息时,会触发这个事件this.tcpSocket.on('message', (data: socket.SocketMessageInfo): void => {try {this.addLog('收到服务器消息');// 把服务器返回的二进制数据,转成字符串const messageStr: string = this.ab2str(data.message);this.addLog(`原始数据: ${messageStr}`);// 把字符串转成我们定义的ResponseData格式(方便解析)const response: ResponseData = JSON.parse(messageStr) as ResponseData;// 处理服务器返回的响应(显示结果、弹提示)this.handleResponse(response);} catch (error) {this.addLog(`解析消息失败: ${error}`, true);}});// 监听「连接关闭」事件:服务器断开连接,或客户端主动断开时触发this.tcpSocket.on('close', (): void => {this.addLog('TCP连接已关闭');this.isConnected = false; // 更新连接状态为未连接this.connectionStatus = '已断开'; // 更新界面显示// 弹提示,告诉用户连接已断开promptAction.showToast({message: '连接已断开',duration: 2000 // 提示显示2秒});});// 监听「错误」事件:连接、发送、接收过程中出错时触发this.tcpSocket.on('error', (err: BusinessError): void => {this.addLog(`TCP错误: ${err.message}`, true);this.isConnected = false; // 更新连接状态this.connectionStatus = '连接错误'; // 更新界面显示// 弹提示,显示错误信息promptAction.showToast({message: `错误: ${err.message}`,duration: 2000});});this.addLog('Socket初始化成功');} catch (error) {this.addLog(`初始化Socket失败: ${error}`, true);}}

重点提醒:初始化Socket时,必须绑定这3个事件(message、close、error),否则收不到消息、不知道连接是否断开、出错了也找不到原因。

(2)连接服务器(最常用,新手重点看)

点击界面上的「连接服务器」按钮,就会调用这个方法,里面做了IP、端口校验,避免无效连接。

typescript// 连接服务器(异步方法,用async/await,避免卡顿)private async connectToServer(): Promise<void> {// 校验:IP或端口为空,提示用户输入if (!this.serverIp || !this.serverPort) {this.addLog('请输入服务器IP和端口', true);promptAction.showToast({ message: '请输入服务器IP和端口', duration: 2000 });return; // 终止方法,不继续执行}// 校验:端口号必须是数字,且在1-65535之间(TCP端口的有效范围)const port: number = parseInt(this.serverPort);if (isNaN(port) || port <= 0 || port > 65535) {this.addLog('端口号无效 (1-65535)', true);promptAction.showToast({ message: '端口号无效', duration: 2000 });return;}// 校验:IP地址格式是否正确(简单校验,比如192.168.1.100)const ipPattern = /^(\d{1,3}\.){3}\d{1,3}$/;if (!ipPattern.test(this.serverIp)) {this.addLog('IP地址格式无效', true);promptAction.showToast({ message: 'IP地址格式无效', duration: 2000 });return;}// 校验通过,开始尝试连接this.addLog(`尝试连接 ${this.serverIp}:${port}`);this.connectionStatus = '连接中...'; // 更新界面状态try {// 如果Socket没初始化,先初始化if (!this.tcpSocket) {this.initSocket();}this.addLog('正在建立TCP连接...');// 发起TCP连接(鸿蒙自带方法,async/await等待连接结果)await this.tcpSocket!.connect({address: { address: this.serverIp, port: port }, // 服务器IP和端口timeout: 5000 // 连接超时时间:5秒(超过5秒没连上,视为失败)});// 连接成功,更新状态this.isConnected = true;this.connectionStatus = '已连接';this.addLog('✓ 连接成功!');promptAction.showToast({ message: '连接成功', duration: 2000 });} catch (error) {// 连接失败,记录错误日志,更新状态this.addLog(`✗ 连接失败: ${error}`, true);this.connectionStatus = '连接失败';promptAction.showToast({ message: `连接失败: ${error}`, duration: 3000 });}}

新手踩坑点:

IP和端口一定要填对,否则会提示“连接失败”;端口号不能超过65535,也不能是0(无效端口);连接超时时间5秒,可根据自己的需求修改(比如改成10000=10秒)。

(3)断开服务器连接

点击「断开连接」按钮调用,主动断开TCP连接,避免占用资源。

typescript// 断开与服务器的连接(异步方法)private async disconnectFromServer(): Promise<void> {// 只有Socket存在,且处于连接状态,才执行断开操作if (this.tcpSocket && this.isConnected) {try {this.addLog('正在断开连接...');// 调用鸿蒙自带方法,关闭Socket连接await this.tcpSocket.close();// 更新状态this.isConnected = false;this.connectionStatus = '已断开';this.addLog('已断开连接');promptAction.showToast({ message: '已断开连接', duration: 2000 });} catch (error) {this.addLog(`断开失败: ${error}`, true);}}}

(4)发送消息(核心中的核心,所有消息都靠它发送)

不管是Ping测试、回声测试,还是计算指令,最终都是调用这个方法发送消息给服务器。

typescript// 发送消息给服务器(通用方法,所有类型的消息都能发)// data:要发送的数据(符合我们定义的MessageData格式)// 返回值:boolean(true=发送成功,false=发送失败)private async sendMessage(data: MessageData): Promise<boolean> {// 校验:未连接服务器,不能发送消息if (!this.isConnected || !this.tcpSocket) {this.addLog('未连接服务器,无法发送消息', true);promptAction.showToast({ message: '请先连接服务器', duration: 2000 });return false;}try {// 把MessageData格式的数据,转成JSON字符串(方便传输)const jsonStr: string = JSON.stringify(data);this.addLog(`发送: ${jsonStr}`);// 把JSON字符串,转成TCP能发送的二进制数据const sendData: ArrayBuffer = this.str2ab(jsonStr);// 调用鸿蒙自带方法,发送消息await this.tcpSocket.send({data: sendData // 要发送的二进制数据});this.addLog('✓ 消息发送成功');return true; // 发送成功,返回true} catch (error) {this.addLog(`✗ 发送失败: ${error}`, true);promptAction.showToast({ message: '发送失败', duration: 2000 });return false; // 发送失败,返回false}}

通俗理解:发送消息分3步:① 把要发送的内容,按我们定义的格式(MessageData)组装好;② 转成JSON字符串;③ 转成二进制数据;④ 发送给服务器。

(5)具体功能方法(复用sendMessage,不用重复写逻辑)

这3个方法是具体的功能实现,都是调用上面的sendMessage方法,只是组装的消息格式不同。

typescript// 1. 回声测试:发送消息给服务器,服务器原样返回private async sendEchoMessage(): Promise<void> {// 校验:消息为空,提示用户输入if (!this.messageToSend.trim()) {promptAction.showToast({ message: '请输入要发送的消息', duration: 2000 });return;}// 组装回声消息(type为echo,content为输入的消息)const message: MessageData = {type: 'echo',content: this.messageToSend};// 调用发送消息方法await this.sendMessage(message);}// 2. Ping测试:发送心跳消息,服务器返回pong,测试连接是否正常private async sendPingMessage(): Promise<void> {// 组装Ping消息(type为ping,不需要其他参数)const message: MessageData = { type: 'ping' };await this.sendMessage(message);}// 3. 计算功能:发送两个数字和操作符,服务器返回计算结果private async performCalculation(operation: string): Promise<void> {// 把输入的字符串,转成数字const a: number = parseFloat(this.aValue);const b: number = parseFloat(this.bValue);// 校验:输入的不是有效数字,提示用户if (isNaN(a) || isNaN(b)) {promptAction.showToast({ message: '请输入有效的数字', duration: 2000 });return;}// 组装计算消息(type为calculate,携带数字和操作符)const message: MessageData = {type: 'calculate',operation: operation, // 操作符:add(加)、subtract(减)等a: a,b: b};await this.sendMessage(message);}

(6)处理服务器响应(收到消息后,怎么显示结果)

服务器返回消息后,会触发这个方法,根据响应类型(type),显示不同的结果、弹不同的提示。

typescript// 处理服务器返回的响应private handleResponse(response: ResponseData): void {// 把响应数据转成格式化的JSON字符串(方便在界面上显示,换行清晰)const responseStr: string = JSON.stringify(response, null, 2);this.responseMessage = responseStr; // 赋值给界面变量,显示在响应区域this.addLog(`收到响应: ${responseStr}`);// 根据响应类型,做不同的处理if (response.type === 'calculate_response') {// 计算响应:显示计算结果,弹提示this.calculationResult = `${response.result ?? ''}`;promptAction.showToast({message: `计算结果: ${response.result ?? '无结果'}`,duration: 2000});} else if (response.type === 'pong') {// Ping响应:提示收到Pong,说明连接正常promptAction.showToast({message: '收到Pong响应 ✓',duration: 1500});} else if (response.type === 'echo_response') {// 回声响应:提示收到服务器返回的原始消息promptAction.showToast({message: `回声: ${response.original_message}`,duration: 2000});}// 延迟100毫秒,滚动到日志/响应区域底部(显示最新内容)setTimeout(() => {this.scroller.scrollEdge(Edge.Bottom);}, 100);}

6. 界面布局(可视化操作,小白也能上手)

这部分是鸿蒙的UI布局,用Column、Row、Tabs等组件,搭了一个简洁的操作界面,分为「主界面」和「日志」两个标签页,所有操作都能通过界面点击完成,不用写代码。

typescript// 构建界面(鸿蒙UI布局,新手可根据需求修改样式,不影响功能)build() {Column() { // 垂直布局(从上到下排列组件)// 标题Text('TCP 客户端').fontSize(24).fontWeight(FontWeight.Bold).margin({ top: 20, bottom: 10 })// 连接状态栏(显示当前连接状态,绿色=已连接,红色=未连接)Row() { // 水平布局(从左到右排列组件)Text('状态:').fontSize(14)Text(this.connectionStatus).fontSize(14).fontColor(this.isConnected ? '#28a745' : '#dc3545') // 连接成功绿色,失败红色.margin({ left: 5 })Blank() // 空白占位,把后面的内容推到右侧Text(this.isConnected ? '● 在线' : '○ 离线').fontSize(12).fontColor(this.isConnected ? '#28a745' : '#999')}.width('100%').padding(10).backgroundColor('#f0f0f0').margin({ bottom: 10 })// 标签页(主界面+日志)Tabs() {// 第一个标签页:主界面(核心操作区域)TabContent() {Scroll(this.scroller) { // 滚动布局(内容太多时可滚动)Column() {// 1. 服务器配置区域(输入IP、端口,连接/断开)Column() {Text('服务器配置').fontSize(18).fontWeight(FontWeight.Medium).margin({ bottom: 10 })// IP输入框Row() {Text('IP:').width(50).fontSize(14)TextInput({ text: this.serverIp, placeholder: '例如: 192.168.1.100' }).layoutWeight(1) // 占满剩余宽度.height(40).onChange((value: string): void => {this.serverIp = value; // 输入框内容变化,更新变量})}.margin({ bottom: 10 })// 端口输入框(只能输入数字)Row() {Text('端口:').width(50).fontSize(14)TextInput({ text: this.serverPort, placeholder: '8888' }).layoutWeight(1).height(40).type(InputType.Number) // 输入类型为数字,避免输入字母.onChange((value: string): void => {this.serverPort = value;})}.margin({ bottom: 15 })// 连接/断开按钮(根据连接状态切换文本和颜色)Button(this.isConnected ? '断开连接' : '连接服务器').width('100%').height(44).backgroundColor(this.isConnected ? '#dc3545' : '#28a745').onClick((): void => {// 点击按钮,根据连接状态,调用连接或断开方法if (this.isConnected) {this.disconnectFromServer();} else {this.connectToServer();}})}.padding(15).backgroundColor('#f8f9fa').borderRadius(10).margin({ bottom: 20 })// 2. 消息测试区域(Ping测试、回声测试)Column() {Text('消息测试').fontSize(18).fontWeight(FontWeight.Medium).margin({ bottom: 10 })// Ping和回声测试按钮Row() {Button('Ping测试').height(40).layoutWeight(1).backgroundColor('#17a2b8').fontSize(14).onClick((): void => {this.sendPingMessage(); // 点击调用Ping测试})Button('回声测试').height(40).layoutWeight(1).backgroundColor('#ffc107').margin({ left: 10 }).fontSize(14).onClick((): void => {this.sendEchoMessage(); // 点击调用回声测试})}.width('100%').margin({ bottom: 10 })// 回声测试消息输入框TextInput({ text: this.messageToSend, placeholder: '输入要发送的消息' }).height(40).margin({ bottom: 10 }).onChange((value: string): void => {this.messageToSend = value;})}.padding(15).backgroundColor('#f8f9fa').borderRadius(10).margin({ bottom: 20 })// 3. 计算器测试区域(发送计算指令)Column() {Text('计算器测试').fontSize(18).fontWeight(FontWeight.Medium).margin({ bottom: 10 })// 数字A和数字B输入框Row() {TextInput({ text: this.aValue, placeholder: '数字A' }).layoutWeight(1).height(40).type(InputType.Number).onChange((value: string): void => {this.aValue = value;})Text('+').margin({ left: 5, right: 5 }).fontSize(18)TextInput({ text: this.bValue, placeholder: '数字B' }).layoutWeight(1).height(40).type(InputType.Number).onChange((value: string): void => {this.bValue = value;})}.margin({ bottom: 10 })// 加减乘除按钮Row() {Button('加法').height(40).layoutWeight(1).backgroundColor('#28a745').fontSize(12).onClick(() => this.performCalculation('add')) // 调用计算方法,传addButton('减法').height(40).layoutWeight(1).backgroundColor('#28a745').margin({ left: 5 }).fontSize(12).onClick(() => this.performCalculation('subtract'))Button('乘法').height(40).layoutWeight(1).backgroundColor('#28a745').margin({ left: 5 }).fontSize(12).onClick(() => this.performCalculation('multiply'))Button('除法').height(40).layoutWeight(1).backgroundColor('#28a745').margin({ left: 5 }).fontSize(12).onClick(() => this.performCalculation('divide'))}.width('100%')// 显示计算结果(有结果才显示)if (this.calculationResult) {Text(`结果: ${this.calculationResult}`).margin({ top: 10 }).fontColor('#28a745').fontSize(16)}}.padding(15).backgroundColor('#f8f9fa').borderRadius(10).margin({ bottom: 20 })// 4. 服务器响应显示区域(显示服务器返回的原始响应)Column() {Text('服务器响应').fontSize(18).fontWeight(FontWeight.Medium).margin({ bottom: 10 })// 有响应就显示响应内容,没有就显示“暂无响应”if (this.responseMessage) {Text(this.responseMessage).width('100%').padding(10).backgroundColor('#e9ecef').borderRadius(5).fontSize(11).fontColor('#666')} else {Text('暂无响应').width('100%').height(80).padding(10).backgroundColor('#e9ecef').borderRadius(5).fontSize(12).fontColor('#999')}}.padding(15).backgroundColor('#f8f9fa').borderRadius(10).margin({ bottom: 20 })}.padding({ left: 20, right: 20, bottom: 20 })}.scrollable(ScrollDirection.Vertical) // 垂直滚动.scrollBar(BarState.Auto) // 自动显示滚动条.width('100%').height('100%')}.tabBar('主界面') // 标签页标题// 第二个标签页:日志(显示所有调试信息,找bug必备)TabContent() {Column() {Text('调试日志').fontSize(18).fontWeight(FontWeight.Medium).margin(15)// 日志列表(显示所有日志条目)List() {ForEach(this.logMessages, (log: string, index: number) => {ListItem() {Text(log).fontSize(11).padding(8).width('100%').textAlign(TextAlign.Start)}}, (log: string, index: number) => index.toString())}.layoutWeight(1).backgroundColor('#f8f9fa').margin(10).borderRadius(10)// 清空日志按钮Button('清空日志').width('90%').height(40).margin(10).onClick((): void => {this.logMessages = []; // 清空日志数组})}.width('100%').height('100%')}.tabBar('日志') // 标签页标题}.vertical(false).barMode(BarMode.Fixed).barWidth('50%') // 两个标签页,各占50%宽度.width('100%').height('100%')}.width('100%').height('100%').backgroundColor('#f5f5f5') // 整体背景色}}

新手提示:界面布局可以根据自己的喜好修改,比如修改颜色、字体大小、按钮样式,只要不改动「onClick」里面的方法调用,就不会影响功能。

第三步:新手必看(避坑指南+使用步骤)

1. 使用步骤(直接照做,就能跑通)

复制上面所有代码,粘贴到鸿蒙Stage模型的Index.ets文件中;修改「serverIp」和「serverPort」,改成自己的TCP服务器IP和端口;运行APP,在主界面输入正确的IP和端口,点击「连接服务器」;连接成功后,可进行Ping测试、回声测试、计算器测试;遇到问题,切换到「日志」标签页,查看错误信息,对照日志找bug。

2. 常见坑及解决方法(新手必看)

坑1:连接失败,日志显示“初始化Socket失败”——检查鸿蒙SDK版本,必须是API 9及以上,Stage模型;坑2:连接失败,提示“端口无效”——端口号必须是1-65535之间的数字,不能是字母或其他符号;坑3:发送消息失败,提示“未连接服务器”——先点击「连接服务器」,确认状态显示“已连接”再发送;坑4:收到消息乱码——检查ab2str和str2ab方法,确保编码格式是UTF-8(不要修改成其他编码);坑5:解析消息失败——检查服务器返回的数据格式,必须符合我们定义的ResponseData接口(和服务器约定好格式)。

第四步:总结(重点回顾)

这份鸿蒙TCP客户端代码,核心就是「初始化Socket→连接服务器→发送消息→接收响应→断开连接」,所有方法都做了封装和注释,小白也能看懂、能用。

关键重点:

数据格式必须规范(用接口定义),否则会解析失败;字符串和二进制必须转换(ab2str和str2ab方法),否则会乱码;连接前必须校验IP和端口,避免无效连接;日志功能一定要保留,找bug全靠它。

最后,大家可以根据自己的需求,修改代码(比如增加更多消息类型、修改界面样式),复制粘贴就能复用,不用从零开始写TCP通信代码,省时又省力!

如果运行中遇到问题,评论区留言,我会一一解答~