0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入淺出學(xué)習(xí)eTs之TCP聊天的功能實(shí)現(xiàn)

Harmony&嵌入式學(xué)習(xí) ? 來(lái)源:Harmony&嵌入式學(xué)習(xí) ? 作者:Harmony&嵌入式學(xué) ? 2023-05-13 13:27 ? 次閱讀

一、需求分析

wKgZomRfH9iAHR7gAARCUmVyfbg568.png

本章節(jié)我們來(lái)實(shí)現(xiàn)一個(gè)TCP聊天的功能

連接指定IP和端口

顯示接收的內(nèi)容

具有發(fā)送的功能

二、控件介紹

(1)Socket連接

場(chǎng)景介紹

應(yīng)用通過(guò)Socket進(jìn)行數(shù)據(jù)傳輸,支持TCP和UDP兩種協(xié)議。

接口說(shuō)明

Socket連接主要由socket模塊提供。具體接口說(shuō)明如下表。

接口名 功能描述
constructUDPSocketInstance() 創(chuàng)建一個(gè)UDPSocket對(duì)象。
constructTCPSocketInstance() 創(chuàng)建一個(gè)TCPSocket對(duì)象。
bind() 綁定IP地址和端口。
send() 發(fā)送數(shù)據(jù)。
close() 關(guān)閉連接。
getState() 獲取Socket狀態(tài)。
connect() 連接到指定的IP地址和端口(僅TCP支持)
getRemoteAddress() 獲取對(duì)端Socket地址(僅TCP支持,需要先調(diào)用connect方法)
on(type: ‘message’) 訂閱Socket連接的接收消息事件。
off(type: ‘message’) 取消訂閱Socket連接的接收消息事件。
on(type: ‘close’) 訂閱Socket連接的關(guān)閉事件。
off(type: ‘close’) 取消訂閱Socket連接的關(guān)閉事件。
on(type: ‘error’) 訂閱Socket連接的Error事件。
off(type: ‘error’) 取消訂閱Socket連接的Error事件。
on(type: ‘listening’) 訂閱UDPSocket連接的數(shù)據(jù)包消息事件(僅UDP支持)。
off(type: ‘listening’) 取消訂閱UDPSocket連接的數(shù)據(jù)包消息事件(僅UDP支持)。
on(type: ‘connect’) 訂閱TCPSocket的連接事件(僅TCP支持)。
off(type: ‘connect’) 取消訂閱TCPSocket的連接事件(僅TCP支持)。

基本例程(參考我之前的家庭醫(yī)生終端系統(tǒng))

import socket from '@ohos.net.socket';
let tcp = socket.constructTCPSocketInstance();

tcp.bind({address: '0.0.0.0', port: 12121, family: 1}, err => {
  if (err) {
    console.log('bind fail');
    return;
  }
  console.log('bind success');
})

tcp.on('message', value => {
  console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo)
  let da = resolveArrayBuffer(value.message);
  let dat_buff = String(da);
//此處對(duì)接受到的數(shù)據(jù)進(jìn)行處理


});
//將接受到的數(shù)據(jù)轉(zhuǎn)化為文本型           
function resolveArrayBuffer(message){

  if (message instanceof ArrayBuffer) {
    let dataView = new DataView(message)
    let str = ""
    for (let i = 0;i < dataView.byteLength; ++i) {
      let c = String.fromCharCode(dataView.getUint8(i))
      if (c !== "n") {
        str += c
      }
    }
    return str;
  }
}
//數(shù)據(jù)的發(fā)送函數(shù)
function send_once(Con_buff) {
  if (flag == false) {

    let promise = tcp.connect({ address: { address: 'xxx.xxx.xxx.xxx', port: xxxx, family: 1 }, timeout: 2000 });
    promise.then(() => {
      console.log('connect success');
      flag = true;
      tcp.send({
        data: Con_buff
      }, err => {
        if (err) {
          console.log('send fail');
          return;
        }
        console.log('send success');
      })
    }).catch(err => {
      console.log('connect fail');
    });

  } else if (flag == true) {
    tcp.send({
      data: Con_buff
    }, err => {
      if (err) {
        console.log('send fail');
        return;
      }
      console.log('send success');
    })
  }
}

(2)AppStorage與組件同步

在管理組件擁有的狀態(tài)中,已經(jīng)定義了如何將組件的狀態(tài)變量與父組件或祖先組件中的@State裝飾的狀態(tài)變量同步,主要包括@Prop、@Link、@Consume。

本章節(jié)定義如何將組件變量與AppStorage同步,主要提供@StorageLink和@StorageProp裝飾器。

@StorageLink裝飾器

組件通過(guò)使用@StorageLink(key)裝飾的狀態(tài)變量,與AppStorage建立雙向數(shù)據(jù)綁定,key為AppStorage中的屬性鍵值。當(dāng)創(chuàng)建包含@StorageLink的狀態(tài)變量的組件時(shí),該狀態(tài)變量的值將使用AppStorage中的值進(jìn)行初始化。在UI組件中對(duì)@StorageLink的狀態(tài)變量所做的更改將同步到AppStorage,并從AppStorage同步到任何其他綁定實(shí)例中,如PersistentStorage或其他綁定的UI組件。

@StorageProp裝飾器

組件通過(guò)使用@StorageProp(key)裝飾的狀態(tài)變量,將與AppStorage建立單向數(shù)據(jù)綁定,key標(biāo)識(shí)AppStorage中的屬性鍵值。當(dāng)創(chuàng)建包含@StoageProp的狀態(tài)變量的組件時(shí),該狀態(tài)變量的值將使用AppStorage中的值進(jìn)行初始化。AppStorage中的屬性值的更改會(huì)導(dǎo)致綁定的UI組件進(jìn)行狀態(tài)更新。

let varA = AppStorage.Link('varA')
let envLang = AppStorage.Prop('languageCode')
@Entry
@Component
struct ComponentA {
  @StorageLink('varA') varA: number = 2
  @StorageProp('languageCode') lang: string = 'en'
  private label: string = 'count'

  private aboutToAppear() {
    this.label = (this.lang === 'zh') ? '數(shù)' : 'Count'
  }

  build() {
    Row({ space: 20 }) {

      Button(`${this.label}: ${this.varA}`)
        .onClick(() => {
          AppStorage.Set('varA', AppStorage.Get('varA') + 1)
        })
      Button(`lang: ${this.lang}`)
        .onClick(() => {
          if (this.lang === 'zh') {
            AppStorage.Set('languageCode', 'en')
          } else {
            AppStorage.Set('languageCode', 'zh')
          }
          this.label = (this.lang === 'zh') ? '數(shù)' : 'Count'
        })
    }
  }
}

即通過(guò)AppStorage.Link和 @StorageLink的方式,可實(shí)現(xiàn)外部動(dòng)態(tài)刷新Text組件和image組件(等等之類都可以),方便我們?cè)谌终{(diào)用時(shí)更新數(shù)據(jù)。

三、UI設(shè)計(jì)

本項(xiàng)目的基本內(nèi)容是可以在預(yù)覽器中看到的,所以先在預(yù)覽器中簡(jiǎn)單設(shè)計(jì)UI

(1)基本界面

wKgaomRfH9iAXkxLAACH9xv0dpY079.png

以后不會(huì)大時(shí)間講解UI了,會(huì)直接放成品,且我的源碼都在Gitee倉(cāng)上存在,需要的可以自己下載,會(huì)著重體現(xiàn)程序部分

(2)接口綁定

首先是接收框處的變量綁定

let Rc_message = AppStorage.Link('Rc_message')
@StorageLink('Rc_message') Rc_message: String = '收到消息'
      Text(`${this.Rc_message}`)
        .width("98%")
        .height("35%")
        .borderStyle(BorderStyle.Solid).borderWidth(8).borderColor(0xAFEEEE).borderRadius(20)
        .fontSize(25)

(3)TCP回調(diào)設(shè)置

tcp.on('message', value => {
  console.log("on message, message:" + value.message + ", remoteInfo:" + value.remoteInfo)
  let da = resolveArrayBuffer(value.message);
  let dat_buff = String(da);
  AppStorage.Set('Rc_message',dat_buff);
//AppStorage.Set('ID_1_stata','rgba(0, 109, 229, 0.95)');
});

該部分實(shí)現(xiàn)聊天框內(nèi)部的文字刷新

(4)IP設(shè)置

這里我是使用的合宙的TCP工具[wstool (luatos.com)](

wKgZomRfH9mAfeieAABRQ6an6lE467.png

在此處修改IP和端口

wKgaomRfH9mAR_YJAADyC-hJSMw960.png

(5)遠(yuǎn)端模擬

wKgZomRfH9qAcLNSAAFD_6-9MIY732.png

在模擬器中打開(kāi)如上

四、實(shí)際測(cè)試

wKgaomRfH9qAKrexAAEkrnzdjrY871.png

使用模擬器進(jìn)行發(fā)送

wKgZomRfH9uAV7aaAACOqG6V6WE909.png

在TCP工具處有接收到內(nèi)容,此時(shí)進(jìn)行回復(fù)

wKgaomRfH9yADI94AABvBsINwBE053.png

在APP端可以接收到并顯示(暫時(shí)可能只支持英文接受顯示)

wKgZomRfH9yASo__AAEjyjkuI_U462.png


wKgaomRfH92AHGRrAACM1tKj4Nc016.png


wKgZomRfH92AXr8PAAErrS-4flY198.png

五、動(dòng)態(tài)圖

wKgaomRfH96AC6OtAAmOwGpABEI516.gif

TCP助手顯示如下

wKgZomRfH96AQflyAACkliKb1l8025.png


編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1374

    瀏覽量

    79157
  • UDP
    UDP
    +關(guān)注

    關(guān)注

    0

    文章

    327

    瀏覽量

    34003
  • ets
    ets
    +關(guān)注

    關(guān)注

    0

    文章

    20

    瀏覽量

    1624
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3730

    瀏覽量

    16424
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    #深入淺出學(xué)習(xí)eTs#(八)“猜大小”小游戲

    本項(xiàng)目Gitee倉(cāng)地址:[深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)
    的頭像 發(fā)表于 05-17 15:08 ?1045次閱讀
    #<b class='flag-5'>深入淺出</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>eTs</b>#(八)“猜大小”小游戲

    #深入淺出學(xué)習(xí)eTs#(十)藍(lán)藥丸還是紅藥丸

    本項(xiàng)目Gitee倉(cāng)地址: 深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)
    的頭像 發(fā)表于 05-17 15:07 ?974次閱讀
    #<b class='flag-5'>深入淺出</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>eTs</b>#(十)藍(lán)藥丸還是紅藥丸

    ARM7 深入淺出學(xué)習(xí)

    深入淺出ARM7 LPC213x_214 學(xué)習(xí)
    發(fā)表于 12-04 17:28

    深入淺出Android

    深入淺出Android
    發(fā)表于 04-26 10:48

    深入淺出排序學(xué)習(xí)使用指南

    深入淺出排序學(xué)習(xí):寫給程序員的算法系統(tǒng)開(kāi)發(fā)實(shí)踐
    發(fā)表于 09-16 11:38

    #深入淺出學(xué)習(xí)eTs#(六)編寫eTs第一個(gè)控件

    本項(xiàng)目Gitee倉(cāng)地址:深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)一
    發(fā)表于 12-29 10:05

    #深入淺出學(xué)習(xí)eTs#(七)判斷密碼是否正確

    本項(xiàng)目Gitee倉(cāng)地址:深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)一
    發(fā)表于 12-29 10:06

    #深入淺出學(xué)習(xí)eTs#(十九)TCP聊天

    本項(xiàng)目Gitee倉(cāng)地址:深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)一
    發(fā)表于 12-29 13:59

    深入淺出Cortex-M0學(xué)習(xí)資料

    深入淺出Cortex-M0學(xué)習(xí)資料
    發(fā)表于 06-18 10:50 ?0次下載
    <b class='flag-5'>深入淺出</b>Cortex-M0<b class='flag-5'>學(xué)習(xí)</b>資料

    STM32深入淺出新手篇

    STM32深入淺出新手篇,很好的單片機(jī)學(xué)習(xí)資料。
    發(fā)表于 03-21 17:43 ?128次下載

    深入淺出學(xué)習(xí)250個(gè)通信原理資源下載

    深入淺出學(xué)習(xí)250個(gè)通信原理資源下載
    發(fā)表于 04-12 09:16 ?28次下載

    深入淺出學(xué)習(xí)低功耗藍(lán)牙協(xié)議棧

    深入淺出學(xué)習(xí)低功耗藍(lán)牙協(xié)議棧
    發(fā)表于 06-23 10:35 ?57次下載

    深入淺出學(xué)習(xí)eTs(一)模擬器/真機(jī)環(huán)境搭建

    本項(xiàng)目的Gitee倉(cāng)地址: 深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com
    的頭像 發(fā)表于 05-13 13:17 ?1728次閱讀
    <b class='flag-5'>深入淺出</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>eTs</b>(一)模擬器/真機(jī)環(huán)境搭建

    深入淺出學(xué)習(xí)eTs(七)如何判斷密碼是否正確

    本項(xiàng)目Gitee倉(cāng)地址: 深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)
    的頭像 發(fā)表于 05-13 13:20 ?927次閱讀
    <b class='flag-5'>深入淺出</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>eTs</b>(七)如何判斷密碼是否正確

    深入淺出學(xué)習(xí)eTs九宮格密碼鎖功能實(shí)現(xiàn)

    本項(xiàng)目Gitee倉(cāng)地址:深入淺出eTs學(xué)習(xí): 帶大家深入淺出學(xué)習(xí)eTs (gitee.com)
    的頭像 發(fā)表于 05-13 13:25 ?1612次閱讀
    <b class='flag-5'>深入淺出</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>eTs</b><b class='flag-5'>之</b>九宮格密碼鎖<b class='flag-5'>功能</b><b class='flag-5'>實(shí)現(xiàn)</b>