鸿蒙Socket通信示例(TCP通信)

news2025/1/14 19:21:06

前言

DevEco Studio版本:4.0.0.600

参考链接:OpenHarmony Socket

效果

TCPSocket

1、bind绑定本地IP地址

private bindTcpSocket() {
   let localAddress = resolveIP(wifi.getIpInfo().ipAddress)
   console.info("111111111  localAddress: " + localAddress);

   //bind本地地址
   tcpSocket.bind({ address: localAddress })
      .then(() => {
         console.info("111111111 绑定Tcp成功");
      })
      .catch(err => {
         console.info("111111111 绑定Tcp失败,原因: " + err);
      });
}

2、设置tcpSocket的监听

private tcpSocketListener() {
   tcpSocket.on('connect', () => {
      this.connectMessage = '已连接'
      console.info("111111111  监听: 连接成功");
   });

   tcpSocket.on('message', (value: {
      message: ArrayBuffer,
      remoteInfo: socket.SocketRemoteInfo
   }) => {
      this.messageReceive = this.messageReceive + this.resolveArrayBuffer(value.message) + "\n"
      console.info("111111111  接收服务器的数据: " + this.messageReceive);
   });
   tcpSocket.on('close', () => {
      this.connectMessage = '未连接'
      console.info("111111111   监听:关闭连接")
   });
}

3、连接服务器

private tcpSocketConnect() {
   //开始连接
   tcpSocket.connect({
      address: { address: connectAddress.address, port: connectAddress.port, family: connectAddress.family },
      timeout: 6000
   }).then(() => {
      console.info("111111111   tcpSocketConnect:连接成功");

      let tcpExtraOptions: socket.TCPExtraOptions = {
         keepAlive: true, //是否保持连接。默认为false
         OOBInline: true, //是否为OOB内联。默认为false
         TCPNoDelay: true, //TCPSocket连接是否无时延。默认为false
         socketLinger: {
            on: true,
            linger: 10
         }, //socket是否继续逗留。- on:是否逗留(true:逗留;false:不逗留)。- linger:逗留时长,单位毫秒(ms),取值范围为0~65535。当入参on设置为true时,才需要设置。
         receiveBufferSize: 1000, //接收缓冲区大小(单位:Byte),默认为0
         sendBufferSize: 1000, //发送缓冲区大小(单位:Byte),默认为0。
         reuseAddress: true, //是否重用地址。默认为false。
         socketTimeout: 3000//套接字超时时间,单位毫秒(ms),默认为0。
      }
      tcpSocket.setExtraOptions(tcpExtraOptions, (err: BusinessError) => {
         if (err) {
            console.log('111111111   setExtraOptions 失败');
            return;
         }
         console.log('111111111  setExtraOptions 成功');
      });

   }).catch((error) => {
      console.info("111111111  tcpSocketConnect 连接失败,原因: " + JSON.stringify(error));
   })
}

4、发送数据内容

private sendMessage() {
   tcpSocket.getState().then((data) => {
      console.info("111111111 连接状态: " + JSON.stringify(data))
      //已连接
      if (data.isConnected) {
         //发送消息
         tcpSocket.send({ data: `${this.inputContent}\n`, encoding: 'UTF-8' })
            .then(() => {
               this.messageReceive = this.messageReceive + "发送:" + this.inputContent + "\n"
               console.info("111111111  消息发送成功");
            })
            .catch((error) => {
               console.info("111111111  消息发送失败,原因:" + JSON.stringify(error));
            })
      } else {
         console.info("111111111  没有连接");
         this.connectMessage = '未连接,服务器断了'
      }
   })
}

5、结束释放资源

private tcpSocketRelease() {
   tcpSocket.off("message")
   tcpSocket.off("connect")
   tcpSocket.off("close")
   tcpSocket.close()
   tcpSocket = null
}

6、UI实现

build() {
   Column() {
      TextInput({ placeholder: '请输入用户名', text: '测试数据:Test' })
         .width('100%')
         .margin({ top: 20, bottom: 20 })
         .onChange((value: string) => {
            this.inputContent = value
         })

      Button('发送数据')
         .width('100%')
         .margin({ top: 20, bottom: 20 })
         .onClick(() => {
            this.sendMessage()
         })

      Text() {
         Span('连接状态:')
         Span(this.connectMessage).fontColor(Color.Red)
      }

      Scroll() {
         Column() {
            Text() {
               Span('内容:\n')
               Span(this.messageReceive).fontColor(Color.Pink)
            }
         }.width('100%')
         .alignItems(HorizontalAlign.Start)
      }
      .width("100%")
      .alignSelf(ItemAlign.Start)
      .flexShrink(1)
      .margin({ top: 15 })
   }
   .alignItems(HorizontalAlign.Start)
   .padding({ left: 15, right: 15 })
   .width('100%')
   .height('100%')
}

详细代码

1、Index.ets

import socket from '@ohos.net.socket';
import wifi from '@ohos.wifi';
import { BusinessError } from '@ohos.base';
import { resolveIP } from '../utils/IpUtil';
import util from '@ohos.util';

//tcp连接对象
let tcpSocket = socket.constructTCPSocketInstance();

//连接服务器的地址和端口
let connectAddress = {
   address: '10.65.XX.XX', //要通信的 PC地址,CMD--->ipconfig查看
   family: 1,
   port: 6666
}

@Entry
@Component
struct Index {
   @State connectMessage: string = '未连接'
   @State messageReceive: string = ''
   @State inputContent: string = ''

   aboutToAppear() {
      this.tcpSocketListener()
      this.bindTcpSocket()
   }

   onPageShow() {
      this.tcpSocketConnect()
   }

   onPageHide() {
      this.tcpSocketRelease()
   }

   build() {
      Column() {
         TextInput({ placeholder: '请输入用户名', text: '测试数据:Test' })
            .width('100%')
            .margin({ top: 20, bottom: 20 })
            .onChange((value: string) => {
               this.inputContent = value
            })

         Button('发送数据')
            .width('100%')
            .margin({ top: 20, bottom: 20 })
            .onClick(() => {
               this.sendMessage()
            })

         Text() {
            Span('连接状态:')
            Span(this.connectMessage).fontColor(Color.Red)
         }

         Scroll() {
            Column() {
               Text() {
                  Span('内容:\n')
                  Span(this.messageReceive).fontColor(Color.Pink)
               }
            }.width('100%')
            .alignItems(HorizontalAlign.Start)
         }
         .width("100%")
         .alignSelf(ItemAlign.Start)
         .flexShrink(1)
         .margin({ top: 15 })
      }
      .alignItems(HorizontalAlign.Start)
      .padding({ left: 15, right: 15 })
      .width('100%')
      .height('100%')
   }

   /**
    * tcp连接状态和消息监听
    */
   private tcpSocketListener() {
      tcpSocket.on('connect', () => {
         this.connectMessage = '已连接'
         console.info("111111111  监听: 连接成功");
      });

      tcpSocket.on('message', (value: {
         message: ArrayBuffer,
         remoteInfo: socket.SocketRemoteInfo
      }) => {
         this.messageReceive = this.messageReceive + this.resolveArrayBuffer(value.message) + "\n"
         console.info("111111111  接收服务器的数据: " + this.messageReceive);
      });
      tcpSocket.on('close', () => {
         this.connectMessage = '未连接'
         console.info("111111111   监听:关闭连接")
      });
   }

   /**
    * 绑定Tcp本地地址
    * bind的IP为'localhost'或'127.0.0.1'时,只允许本地回环接口的连接,即服务端和客户端运行在同一台机器上
    */
   private bindTcpSocket() {
      let localAddress = resolveIP(wifi.getIpInfo().ipAddress)
      console.info("111111111  localAddress: " + localAddress);

      //bind本地地址
      tcpSocket.bind({ address: localAddress })
         .then(() => {
            console.info("111111111 绑定Tcp成功");
         })
         .catch(err => {
            console.info("111111111 绑定Tcp失败,原因: " + err);
         });
   }

   /**
    * 发送消息数据
    */
   private sendMessage() {
      tcpSocket.getState().then((data) => {
         console.info("111111111 连接状态: " + JSON.stringify(data))
         //已连接
         if (data.isConnected) {
            //发送消息
            tcpSocket.send({ data: `${this.inputContent}\n`, encoding: 'UTF-8' })
               .then(() => {
                  this.messageReceive = this.messageReceive + "发送:" + this.inputContent + "\n"
                  console.info("111111111  消息发送成功");
               })
               .catch((error) => {
                  console.info("111111111  消息发送失败,原因:" + JSON.stringify(error));
               })
         } else {
            console.info("111111111  没有连接");
            this.connectMessage = '未连接,服务器断了'
         }
      })
   }

   /**
    * 连接服务器
    */
   private tcpSocketConnect() {
      //开始连接
      tcpSocket.connect({
         address: { address: connectAddress.address, port: connectAddress.port, family: connectAddress.family },
         timeout: 6000
      }).then(() => {
         console.info("111111111   tcpSocketConnect:连接成功");

         let tcpExtraOptions: socket.TCPExtraOptions = {
            keepAlive: true, //是否保持连接。默认为false
            OOBInline: true, //是否为OOB内联。默认为false
            TCPNoDelay: true, //TCPSocket连接是否无时延。默认为false
            socketLinger: {
               on: true,
               linger: 10
            }, //socket是否继续逗留。- on:是否逗留(true:逗留;false:不逗留)。- linger:逗留时长,单位毫秒(ms),取值范围为0~65535。当入参on设置为true时,才需要设置。
            receiveBufferSize: 1000, //接收缓冲区大小(单位:Byte),默认为0
            sendBufferSize: 1000, //发送缓冲区大小(单位:Byte),默认为0。
            reuseAddress: true, //是否重用地址。默认为false。
            socketTimeout: 3000//套接字超时时间,单位毫秒(ms),默认为0。
         }
         tcpSocket.setExtraOptions(tcpExtraOptions, (err: BusinessError) => {
            if (err) {
               console.log('111111111   setExtraOptions 失败');
               return;
            }
            console.log('111111111  setExtraOptions 成功');
         });

      }).catch((error) => {
         console.info("111111111  tcpSocketConnect 连接失败,原因: " + JSON.stringify(error));
      })
   }

   /**
    * 解析ArrayBuffer
    */
   private resolveArrayBuffer(message: ArrayBuffer): string {
      let view = new Uint8Array(message);
      let textDecoder = util.TextDecoder.create()
      let str = textDecoder.decodeWithStream(view);
      console.info("111111111 message 缓存内容: " + str)
      return str;
   }

   /**
    * 关闭Socket监听和连接,释放资源
    */
   private tcpSocketRelease() {
      tcpSocket.off("message")
      tcpSocket.off("connect")
      tcpSocket.off("close")
      tcpSocket.close()
      tcpSocket = null
   }
}

2、IpUtil.ets

export function resolveIP(ip: number): string {
  if (ip < 0 || ip > 0xFFFFFFFF) {
    throw ('The number is not normal!');
  }
  return (ip >>> 24) + '.' + (ip >> 16 & 0xFF) + '.' + (ip >> 8 & 0xFF) + '.' + (ip & 0xFF);
}

3、module.json5配置

因为涉及到网络访问,需要配置网络权限,在module.json5中配置

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"  //联网
  },
  {
    "name": "ohos.permission.GET_NETWORK_INFO"  //获取网络相关信息
  },
  {
    "name": "ohos.permission.SET_NETWORK_INFO" //设置网络相关信息
  },
  {
    "name": "ohos.permission.GET_WIFI_INFO" //获取wifi相关信息
  }
]

服务器端Java代码

package org.example;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketService {
    public static void main(String[] args) {
        int port = 6666;
        try {
            // 创建ServerSocket对象,指定监听的端口号
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("客户端连接: " + clientSocket.getInetAddress().getHostAddress());

                BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);

                String message;
                while ((message = reader.readLine()) != null) {
                    System.out.println("从客户端接收到的消息: " + message);
                    writer.println("回复: " + message);
                }

                reader.close();
                writer.close();
                clientSocket.close();
                System.out.println("连接断开");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1513882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

性能测试总结 —— 测试流程篇!

本文主要介绍下性能测试的基本流程&#xff0c;性能测试从实际执行层面来看&#xff0c;测试的过程一般分为这么几个阶段&#xff0c;如下图&#xff1a;       下面分别介绍下每个阶段具体需要做什么&#xff1a; 一、性能需求分析&#xff1a; 性能需求分析是整个性能…

【PLC】现场总线和工业以太网汇总

1、 现场总线 1.1 什么是现场总线 1&#xff09;非专业描述&#xff1a; 如下图&#xff1a;“人机界面”一般通过以太网连接“控制器(PLC)”&#xff0c;“控制器(PLC)”通过 “现场总线”和现场设备连接。 2&#xff09;专业描述&#xff08;维基百科&#xff09; 现场总线…

MTK安卓开发板_联发科开发板评估套件_安卓主板硬件开发

在介绍开发板之前&#xff0c;让我们先来区分一下核心板和开发板的区别。核心板是一种集成度高、功能完整的计算模块&#xff0c;搭载系统&#xff0c;简化了外围接口&#xff0c;体积尺寸相对较小&#xff0c;主要适用于嵌入式系统。而开发板由核心板底板组成&#xff0c;提供…

探索直播美颜SDK的未来发展方向:虚拟现实、增强现实与混合

如今&#xff0c;随着虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和混合现实&#xff08;MR&#xff09;等技术的不断发展&#xff0c;直播美颜SDK的未来发展方向也将面临着更多的可能性和挑战。今天我将与大家共同探讨直播美颜SDK在虚拟现实、增…

国科大网络行为学导论代码作业--更新中

一、Xray安装 参考自&#xff1a;Xray的安装与使用&#xff08;超详细&#xff09;_xray使用教程-CSDN博客 下载网址&#xff1a;Releases chaitin/xray GitHub 解压 双击安装 生成证书 cd到xray目录&#xff0c;生成证书 复制链接 然后cd到xray目录 .\xray_windows_amd6…

Ubuntu 14.04:PaddleOCR基于PaddleHub Serving的服务部署(失败)

目录 一、为什么使用一键服务部署 二、安装 paddlehub 1.8 2.1 安装前的环境准备 2.2 安装paddlehub 1.8 2.2.1 安装paddlehub 2.2.2 检测安装是否成功 2.2.3 检查本地与远端PaddleHub-Server的连接状态 2.2.4 测试使用 2.3 其他 2.3.1 如何卸载、pip常用命令、常见…

WRF模型运行教程(ububtu系统)--II.ARWpost安装

一、ARWpost简介 ARWpost 是一个把 WRF 结果转为 GrADS 或 Vis5D 可以辨识的数据格式的软件&#xff0c;就是WRF运行结束以后&#xff0c;把WRF的结果变成咱们平时比较常用的数据格式。 二、下载和安装ARWpos_V3 1.ARWpos_V3安装前准备 # 进入Build_WRF文件夹 cd Build_WRF …

代码随想录刷题笔记-Day33

1. 跳跃游戏 55. 跳跃游戏https://leetcode.cn/problems/jump-game/ 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 tru…

【海贼王的数据航海】排序——概念|直接插入排序|希尔排序

目录 1 -> 排序的概念及其运用 1.1 -> 排序的概念 1.2 -> 常见的排序算法 2 -> 插入排序 2.1 -> 基本思想 2.2 -> 直接插入排序 2.2.1 -> 代码实现 2.3 -> 希尔排序(缩小增量排序) 2.3.1 -> 代码实现 1 -> 排序的概念及其运用 1.1 -&g…

【数字调制】OQPSK调制与解调【附MATLAB代码】

文章来源&#xff1a;微信公众号&#xff1a;EW Frontier 关注可了解更多的雷达、通信、人工智能相关代码。 QPSK信号 QPSK信号与BPSK信号的调制方法相同&#xff0c;仅调制阶数不同&#xff0c;其表达式为&#xff1a; 上式中分别表示I、Q两路的基带信息序列&#xff0c;取值…

Xcode remove the package dependency

Xcode Version 15.2 (15C500b) &#x1f914;️ 想知道直接右键&#xff0c;这个 Delete 为什么是禁用状态 推荐一下刚上线的 App 熊猫小账本&#xff0c;里面有用到这篇博客讲的内容 熊猫小账本 一个简洁的记账 App&#xff0c;用于记录日常消费开支收入&#xff0c;使用 iCl…

Pulsar消息路由深入剖析

一、概述 大数据背景下&#xff0c;分区应该是所有组件必备的基本条件&#xff0c;否则面对海量数据时无论是计算还是存储都容易遇到瓶颈。跟其他消息系统一样&#xff0c;Pulsar通过Topic将消息数据进行业务层面划分管理&#xff0c;同时也支持Topic分区&#xff0c;通过将多…

挑战杯 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉

文章目录 0 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习多目标跟踪 …

WRF模型安装教程(ububtu系统)-- III.WRF和WPS模型的安装

六、WRF模型的安装 # 进入Build_WRF文件夹 cd Build_WRF # 下载WRFV3.9.1 wget https://www2.mmm.ucar.edu/wrf/src/WRFV4.0.TAR.gz # 解压WRF安装包并进入 tar -zxvf WRFV4.0.TAR.gz cd WRF # 安装WRF ./configure 出现如下选项&#xff1a; 选择34&#xff0c; 这里是让你选…

React进阶(Redux,RTK,dispatch,devtools)

1、初识Redux 是React最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia(Vuex)&#xff0c;可以独立于框架运行 作用&#xff1a;通过集中管理的方式管理应用的状态 案例-实现一个计数器 实现步骤&#xff1a; Redux管理数据的流程&#xff1a; state:一个对象&…

nRF52832——唯一 ID 与加密解密

nRF52832——唯一 ID 与加密解密 唯一 ID 概念唯一 ID 作用读取唯一 ID 唯一 ID 用于加密TEA 加密算法唯一 ID 的加密和解密 唯一 ID 概念 唯一 ID 作用 nRF52xx 微控制器提供一组 64 位的唯一 ID 号&#xff0c;这个唯一身份标识所提供的 ID 值对任意一个 nRF52xx 微控制器&…

Java项目:51 springboot基于springboot的社区团购系统设计012

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本基于Spring Boot的社区团购系统主要满足两种用户的需求&#xff0c;这两种用户分别为管理员和用户&#xff0c;下面将对这两种用户分别实现的…

电磁兼容EMC:一文读懂电气放电管选型设计

目录 1 GDT外观结构 2 GDT 常见品牌 3 GDT命名规则 4 GDT工作原理 5 GDT基本特点 6 GDT典型应用 7 GDT电气参数说明 7.1 DC Spark-over Voltage 直流火花放电电压&#xff08;直流击穿电压&#xff09; 7.2 Maximum Impulse Spark-over Voltage 最大冲击火花放电电压&…

Ribbon简单使用

Ribbon是Netflix发布的云中间层服务开源项目&#xff0c;其主要功能是提供客户端实现负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时&#xff0c;重试等。简单的说&#xff0c;Ribbon是一个客户端负载均衡器&#xff0c;我们可以在配置文件中Load Balancer后…

【DataWhale学习】用免费GPU线上跑StableDiffusion项目实践

用免费GPU线上跑SD项目实践 ​ DataWhale组织了一个线上白嫖GPU跑chatGLM与SD的项目活动&#xff0c;我很感兴趣就参加啦。之前就对chatGLM有所耳闻&#xff0c;是去年清华联合发布的开源大语言模型&#xff0c;可以用来打造个人知识库什么的&#xff0c;一直没有尝试。而SD我…