当前位置: 首页 > news >正文

鸿蒙网络编程系列53-仓颉版TCP连接超时分析示例

1. TCP连接超时简介

在本系列的第5篇文章《鸿蒙网络编程系列5-TCP连接超时分析》中,介绍了基于ArkTS语言使用TCPSocket对象连接TCP服务端超时的示例。不过,在基于仓颉语言的鸿蒙应用开发中,并没有提供类似的鸿蒙API,幸运的是,仓颉语言自己内置了更强大的TcpSocket对象,可以使用该对象连接TCP服务端。在本系列的第49篇文章《鸿蒙网络编程系列49-仓颉版TCP客户端》中,介绍了TcpSocket对象的connect函数的用法,本文就不再赘述了,不过,我们同样要回答如下的三个问题:

  • 连接的默认超时时间是多少?
  • 如果超时时间设置为0会怎么样?
  • 如果超时时间设置的非常大,比如5分钟,套接字会一直尝试连接吗?

这些问题不太容易回答,官方目前也没有相应的文档,接下来我们将通过一个示例来寻找答案。

2. TCP连接超时示例演示

本示例运行后的页面如图所示:

输入服务端地址和端口后(需确保服务器是真实的,但是端口是不存在的),单击下面的“连接测试”按钮,会发起连接,如图所示:

等选择的测试完成后,再一次单击下面的按钮,最终测试的输入如下所示:

下面是滚动条隐藏的内容:

3. TCP连接超时示例编写

下面详细介绍创建该示例的步骤(确保DevEco Studio已安装仓颉插件)。

步骤1:创建[Cangjie]Empty Ability项目。

步骤2:在module.json5配置文件加上对权限的声明:

"requestPermissions": [{"name": "ohos.permission.INTERNET"}]

这里添加了访问互联网的权限。

步骤3:在build-profile.json5配置文件加上仓颉编译架构:

"cangjieOptions": {"path": "./src/main/cangjie/cjpm.toml","abiFilters": ["arm64-v8a", "x86_64"]}

步骤4:在index.cj文件里添加如下的代码:

package ohos_app_cangjie_entryimport ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*
import std.collection.HashMap
import std.convert.*
import std.net.*
import std.socket.*
import std.time.Duration
import std.time.DateTime@Entry
@Component
class EntryView {@Statevar title: String = '仓颉版TCP连接超时示例';//连接、通讯历史记录@Statevar msgHistory: String = '';//服务端端口号@Statevar serverPort: UInt16 = 9998;//服务端地址@Statevar serverAddress: String = "*.*.*.*";//测试连接按钮是否可用@Statevar testEnable: Bool = truelet scroller: Scroller = Scroller()func build() {Row {Column {Text(title).fontSize(14).fontWeight(FontWeight.Bold).width(100.percent).textAlign(TextAlign.Center).padding(10)Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {Text("服务端地址:").fontSize(14)TextInput(text: serverAddress).onChange({value => serverAddress = value}).width(100).fontSize(11).flexGrow(1)Text(":").fontSize(14)TextInput(text: serverPort.toString()).onChange({value => serverPort = UInt16.parse(value)}).setType(InputType.Number).width(80).fontSize(11)}.width(100.percent).padding(10)TimeoutTestItem(isDefaultTimeout: true, timeout: 0, connectTest: this.connectTest,buttonEnabled: testEnable)TimeoutTestItem(isDefaultTimeout: false, timeout: 0, connectTest: this.connectTest,buttonEnabled: testEnable)TimeoutTestItem(isDefaultTimeout: false, timeout: 3000, connectTest: this.connectTest,buttonEnabled: testEnable)TimeoutTestItem(isDefaultTimeout: false, timeout: 30000, connectTest: this.connectTest,buttonEnabled: testEnable)TimeoutTestItem(isDefaultTimeout: false, timeout: 300000, connectTest: this.connectTest,buttonEnabled: testEnable)Scroll(scroller) {Text(msgHistory).textAlign(TextAlign.Start).width(100.percent).backgroundColor(0xeeeeee)}.align(Alignment.Top).backgroundColor(0xeeeeee).height(300).flexGrow(1).scrollable(ScrollDirection.Vertical).scrollBar(BarState.On).scrollBarWidth(20)}.width(100.percent).height(100.percent)}.height(100.percent)}//连接测试函数func connectTest(isDefaultTimeout: Bool, timeout: Int64) {let tcpClient = TcpSocket(serverAddress, serverPort)if (isDefaultTimeout) {this.msgHistory += "连接超时时间设置:默认\r\n"} else {this.msgHistory += "连接超时时间设置:${timeout}毫秒\r\n"}let start = DateTime.now()this.msgHistory += "连接开始时间:${start.toString("yyyyMMdd HH:mm:ss")}\r\n"this.msgHistory += "正在连接...\r\n"//测试期间禁止点击按钮testEnable = false//启动一个线程进行测试spawn {try {//如果使用默认超时配置,就不配置超时时间if (isDefaultTimeout) {tcpClient.connect()} else { //配置超时时间tcpClient.connect(timeout: Duration.millisecond * timeout)}} catch (err: Exception) {//抛出异常的时间let end = DateTime.now()let period = end - startthis.msgHistory += "连接异常:${err.toString()}\r\n"this.msgHistory += "连接结束时间:${end.toString("yyyyMMdd HH:mm:ss")}\r\n"this.msgHistory += "连接耗时:${period.toMilliseconds()}毫秒\r\n\r\n"}//测试完成允许点击按钮testEnable = true}}
}

步骤5:本示例使用了自定义组件TimeoutTestItem,需要创建TimeoutTestItem.cj文件,然后输入如下的代码:

package ohos_app_cangjie_entryimport ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*@Component
public class TimeoutTestItem {var isDefaultTimeout: Bool = truevar timeout: Int64 = 0//连接测试按钮是否可用@Linkvar buttonEnabled: Bool//测试按钮点击调用的函数@Propvar connectTest: (isDefaultTimeout: Bool, timeout: Int64) -> Future<Unit>func build() {Row {Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {Text(if (this.isDefaultTimeout) {"默认超时时间"} else {"超时时间为${this.timeout / 1000}秒"}).width(150)Text(if (this.isDefaultTimeout) {"default"} else {this.timeout.toString()}).width(150).flexGrow(1)Button("连接测试").onClick {evt => connectTest(this.isDefaultTimeout, this.timeout)}.enabled(buttonEnabled)}.width(100.percent).padding(5)}}
}

步骤6:编译运行,可以使用模拟器或者真机。

步骤7:按照本文第2部分“TCP连接超时示例演示”操作即可。

4. 代码分析

本示例为简化代码,使用自定义组件TimeoutTestItem处理连接测试按钮的点击和状态显示问题,这里面有点复杂的是测试按钮的回调函数,该函数在index.cj中定义,名称为connectTest,接收两个参数,分别表示是否使用默认超时配置以及超时时间。在TimeoutTestItem中,通过变量connectTest指向该函数,并在按钮点击后触发回调。

另外一点需要注意的是,在模拟器和真机环境里,执行的效果是不同的,模拟器可以用来测试,但是要以真机环境运行的为准。在测试的时候,需要确保目标服务器是真实存在的,网络也是通畅的,同时要确保端口不存在,这样就可以实现连接超时的测试了。

根据输出的日志可以分析如下:

1.默认的超时时间为65秒钟

2.超时时间设置为0时,如果连接不上就马上返回,也就是说超时时间就是0

3.设置3秒钟或者30秒钟,实际超时时间就是3秒钟或者30秒钟

4.设置大于65秒的超时时间,实际超时时间为65秒左右

那么,为什么最长超时时间是65秒钟呢?这里分析一下,实际上,TCP连接重试时执行等待时间翻倍的规则,也就是连接失败后等待1秒钟重试,再失败等待2秒钟,然后依次是4秒钟、8秒钟、16秒钟、32秒钟,默认重试5次,也就是1+2+4+8+16+32=63秒钟,再加上其他环节耗费的时间,所以表现出来最大超时时间是65秒左右。

(本文作者原创,除非明确授权禁止转载)

本文源码地址:
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/tcp/TCPTimeout4Cj

本系列源码地址:
https://gitee.com/zl3624/harmonyos_network_samples

相关文章:

  • python中的文件操作处理:文本文件的处理、二进制文件的处理
  • Android音视频多媒体开源框架基础大全
  • 基于Docker实现frp之snowdreamtech/frps
  • window显示驱动开发—为 DirectX VA 2.0 扩展模式提供功能(一)
  • 【JVM】- 类加载与字节码结构1
  • Spring AI详细使用教程:从入门到精通
  • RabbitMQ缓存详解:由来、发展、核心场景与实战应用
  • ubuntu之坑(十四)——安装FFmpeg进行本地视频推流(在海思平台上运行)
  • 软件工程的实践
  • ffmpeg subtitles 字幕不换行的问题解决方案
  • Yarn与NPM缓存存储目录迁移
  • MySQL查询缓存深度剖析
  • ffmpeg rtmp推流源码分析
  • 3GPP协议PDF下载
  • 【信创-k8s】重磅-鲲鹏arm+麒麟V10离线部署k8s1.30+kubesphere4.1.3
  • 从SQL Server到分布式大数据平台:重构企业数据架构
  • 四数之和-力扣
  • Python让自动驾驶“看见未来”:环境建模那些事儿
  • GaussDB 分布式数据库调优(架构到全链路优化)
  • 前端项目Excel数据导出同时出现中英文表头错乱情况解决方案。
  • 手机商城网站模板/商品标题seo是什么意思
  • 陕西住房和建设部网站首页/培训网站建设
  • 百度域名注册与解析服务/网站优化服务
  • 个人网站制作模板响应式/百度宣传广告要多少钱
  • 徐州有哪些做网站/长沙网
  • 网站备案登陆/厦门seo搜索排名