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

前言

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();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

特殊类设计以及C++中的类型转换

1. 请设计一个类&#xff0c;不能被拷贝 拷贝只会放生在两个场景中&#xff1a;拷贝构造函数以及赋值运算符重载&#xff0c;因此想要让一个类禁止拷贝&#xff0c;只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98&#xff1a; 将拷贝构造函数与赋值运算符重载只…

ruoyi-vue插件集成websocket

链接&#xff1a;插件集成 | RuoYi WebSocketServer.java&#xff1a;补充代码 /*** 此为广播消息* param message 消息内容*/public void sendAllMessage(String message) {LOGGER.info("【websocket.sendAllMessage】广播消息:"message);try {for(String sessionI…

观测云在 .NET 业务中分析性能问题的最佳实践

背景 某药业集团是一家以创新技术驱动的线下医疗数据 SaaS 平台建设和运营公司&#xff0c;其主营的某智慧医疗平台产品&#xff0c;围绕线下医疗场景痛点提供一体化服务解决方案。近期集团对其生物检材在线递检系统进行功能升级开发及 IaaS 平台迁移。在针对新系统和新基础设…

云仓酒庄北京朝阳区旗舰店发布活动盛况:红酒品鉴沙龙共筑美好

原标题&#xff1a;云仓酒庄北京朝阳区旗舰店活动盛况&#xff1a;红酒品鉴沙龙与招商交流共筑美好未来 在繁忙的都市中&#xff0c;有一片静谧的天地&#xff0c;那便是云仓酒庄北京朝阳区旗舰店。这里不仅是红酒爱好者的聚集地&#xff0c;更是商业交流的新平台。近日&#…

网络编程-套接字相关基础知识

1.1. Socket简介 套接字&#xff08;socket&#xff09;是一种通信机制&#xff0c;凭借这种机制&#xff0c; 客户端<->服务器 模型的通信方式既可以在本地设备上进行&#xff0c;也可以跨网络进行。 Socket英文原意是“孔”或者“插座”的意思&#xff0c;在网络编程…

2023 年安徽省职业院校技能大赛(高职组)

#需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; 某企业根据自身业务需求&#…

3.Linux/UNIX平台Python的下载、安装和配置环境变量——《跟老吕学Python编程》

3.Linux/UNIX平台Python的下载、安装和配置环境变量——《跟老吕学Python编程》 一、下载Linux/UNIX版Python1.Python官网2.Linux/UNIX版Python下载网址 二、在Linux/UNIX安装Python1.在Ubuntu Linux安装Python1.1 检查Python版本1.2 高级包管理工具1.3 添加存储库1.4 更新软件…

短剧在线搜索源码(全网首发)

一个非常哇塞的在线短剧搜索页面&#xff0c;接口已经对接好了&#xff0c;上传源码到服务器解压就能直接用&#xff0c;有能力的可以自己改接口自己写自己的接口 接口文档地址&#xff1a;doc.djcat.sbs 源码下载地址&#xff1a;https://pan.xunlei.com/s/VNstN8C6N3VK1a1k…

设计模式 -- 2:策略模式

目录 总结部分&#xff1a;策略模式的优点部分代码部分 总结部分&#xff1a; 策略模式和简单工厂模式很像 区别在于 简单工厂模式 需求的是由工程创造的类 去给客户直接答案 而策略模式在于 我有主体 一个主体 根据策略的不同来进行不同的计算 我的主体就负责收钱 然后调度相…

运维专题.Docker+Nginx服务器的SSL证书安装

运维专题 DockerNginx服务器的SSL证书安装 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/q…

力扣977. 有序数组的平方

思路&#xff1a;暴力法&#xff1a;全部平方&#xff0c;然后调用排序API&#xff0c;排序算法最快是N*log(N)时间复制度。 双指针法&#xff1a;要利用好原本的数组本就是有序的数组这个条件&#xff0c; 只是有负数 导致平方后变大了&#xff0c;那么平方后的最大值就是在两…

【机器学习智能硬件开发全解】(三)—— 政安晨:嵌入式系统基本素养【计算机体系结构中的CPU关系】

通过上一篇文章的学习: 【机器学习智能硬件开发全解】&#xff08;二&#xff09;—— 政安晨&#xff1a;嵌入式系统基本素养【处理器原理】https://blog.csdn.net/snowdenkeke/article/details/136662796我们已经知道了CPU的设计流程和工作原理&#xff0c;紧接着一个新问题…

武汉云仓酒庄:品牌细节,用心呈现葡萄酒文化新高度

武汉云仓酒庄&#xff1a;品牌细节&#xff0c;用心呈现葡萄酒文化新高度 在繁忙的武汉都市中&#xff0c;有一处静谧的角落&#xff0c;那便是云仓酒庄。这里不仅仅是葡萄酒的汇聚之地&#xff0c;更是葡萄酒文化传播与交流的重要平台。近日&#xff0c;武汉云仓酒庄以其精心…

【LeetCode热题100】2. 两数相加(链表)

一.题目要求 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数…

面试复盘记录(数据开发)

一、apple外包1.矩阵顺时针旋转遍历2.两表取差集 二、 一、apple外包 没问理论&#xff0c;就两个算法题。 1.矩阵顺时针旋转遍历 Given an m x n matrix, return all elements of the matrix in spiral order.Example 1:Input: matrix [[1,2,3],[4,5,6],[7,8,9]] Output: …

叶子分享站PHP源码

叶子网盘分享站PHP网站源码&#xff0c;创建无限级文件夹&#xff0c;上传文件&#xff0c;可进行删除&#xff0c;下载等能很好的兼容服务器。方便管理者操作&#xff0c;查看更多的下载资源以及文章&#xff0c;新增分享功能&#xff0c;异步上传文件/资源等 PHP网盘源码优势…

VUE内盘期货配资软件源码国际外盘二合一

开发一个Vue内盘期货配资软件源码&#xff0c;同时兼容国际外盘二合一的功能&#xff0c;是一个复杂且专业的任务&#xff0c;涉及前端Vue.js框架的使用、后端服务器处理、数据库管理、实时交易接口对接等多个方面。下面是一些关于开发此类软件的基本指导和考虑因素&#xff1a…

Docker拉取镜像存储不足

在使用Docker时&#xff0c;我们经常遇到一个问题&#xff0c;就是拉取镜像时提示存储空间不足。这是因为Docker在拉取镜像时需要将镜像文件下载到本地存储中&#xff0c;而有时本地存储空间不足以容纳完整的镜像文件。 本文将介绍一些解决这个问题的方法&#xff0c;并提供相…

Diffusion 公式和代码解读

1、训练过程 下面就是代码实现过程 2、训练过程的损失函数。也就是上面的公式。 二、采样过程&#xff0c;生成过程&#xff1a;

BufferWriter类解析

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…