网站建设完毕后怎么加后台给外国小孩 做 英语题用的网站
1. TCP连接超时简介
TCP是面向连接的协议,通过三次握手建立连接,但是,在建立连接的过程中对方有可能没有响应,这时候发起连接的一方会重试,如果重试多次仍然没有响应,就会触发超时,从而导致连接失败,socket的connect方法支持通过参数设置连接超时时间,默认情况下也可以使用缺省的超时时间,那么,问题来了:
- 连接的默认超时时间是多少?
 - 如果超时时间设置为0会怎么样?
 - 如果超时时间设置的非常大,比如5分钟,套接字会一直尝试连接吗?
 
要回答这些问题还不太容易,官方文档也没有给出,下面咱们就自己尝试下,寻找问题的答案。
2.TCP连接超时示例
本示例通过TCP套接字尝试连接一个不存在的IP地址,所以肯定会连接失败,示例中共尝试了5次,第一次使用默认的超时时间,第二次使用0超时时间,第三次使用3秒超时时间,第四次使用30秒超时时间,第五次使用300秒超时时间,每次连接前后都记录下当时的时间,从而方便分析实际耗费的时间。本示例运行后的截图如下所示:

下面详细介绍创建该应用的步骤。
步骤1:创建Empty Ability项目。
步骤2:在module.json5配置文件加上对权限的声明:
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_WIFI_INFO"
}
]
这里分别添加了访问互联网和访问WIFI信息的权限。
步骤3:在Index.ets文件里添加如下的代码:
import socket from '@ohos.net.socket';
 import wifiManager from '@ohos.wifiManager';
 import systemDateTime from '@ohos.systemDateTime';
//说明:本地的IP地址不是必须知道的,绑定时绑定到IP:0.0.0.0即可,显示本地IP地址的目的是方便对方发送信息过来
 //本地IP的数值形式
 let ipNum = wifiManager.getIpInfo().ipAddress
 //本地IP的字符串形式
 let localIp = (ipNum >>> 24) + '.' + (ipNum >> 16 & 0xFF) + '.' + (ipNum >> 8 & 0xFF) + '.' + (ipNum & 0xFF);
@Entry
 @Component
 struct Index {
   //连接、通讯历史记录
   @State msgHistory: string = ''
  //服务端IP地址
   @State serverIp: string = "0.0.0.0"
   //服务端端口
   @State serverPort: number = 9999
   scroller: Scroller = new Scroller()
  build() {
     Row() {
       Column() {
         Text("TCP连接超时演示")
           .fontSize(14)
           .fontWeight(FontWeight.Bold)
           .width('100%')
           .textAlign(TextAlign.Center)
           .padding(10)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("本地IP:")
             .width(100)
             .fontSize(14)
             .flexGrow(0)
           Text(localIp)
             .width(110)
             .fontSize(12)
             .flexGrow(0)
         }.width('100%')
         .padding(5)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("服务端地址:")
             .fontSize(14)
             .width(90)
             .flexGrow(0)
          TextInput({ text: this.serverIp })
             .onChange((value) => {
               this.serverIp = value
             })
             .width(110)
             .fontSize(12)
             .flexGrow(1)
           Text(":")
             .width(5)
             .flexGrow(0)
          TextInput({ text: this.serverPort.toString() })
             .type(InputType.Number)
             .onChange((value) => {
               this.serverPort = parseInt(value)
             })
             .fontSize(12)
             .flexGrow(0)
             .width(60)
         }
         .width('100%')
         .padding(5)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("默认超时时间:")
             .fontSize(14)
             .width(130)
             .flexGrow(0)
          Text("default")
             .width(110)
             .fontSize(12)
             .flexGrow(1)
          Button("连接测试")
             .onClick(() => {
               this.connect2Server(true, 0)
             })
             .width(110)
             .fontSize(14)
             .flexGrow(0)
         }
         .width('100%')
         .padding(5)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("超时时间为0:")
             .fontSize(14)
             .width(130)
             .flexGrow(0)
          Text("0")
             .width(110)
             .fontSize(12)
             .flexGrow(1)
          Button("连接测试")
             .onClick(() => {
               this.connect2Server(false, 0)
             })
             .width(110)
             .fontSize(14)
             .flexGrow(0)
         }
         .width('100%')
         .padding(5)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("超时时间为3秒:")
             .fontSize(14)
             .width(130)
             .flexGrow(0)
          Text("3000")
             .width(110)
             .fontSize(12)
             .flexGrow(1)
          Button("连接测试")
             .onClick(() => {
               this.connect2Server(false, 3000)
             })
             .width(110)
             .fontSize(14)
             .flexGrow(0)
         }
         .width('100%')
         .padding(5)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("超时时间为30秒:")
             .fontSize(14)
             .width(130)
             .flexGrow(0)
          Text("30000")
             .width(110)
             .fontSize(12)
             .flexGrow(1)
          Button("连接测试")
             .onClick(() => {
               this.connect2Server(false, 30000)
             })
             .width(110)
             .fontSize(14)
             .flexGrow(0)
         }
         .width('100%')
         .padding(5)
        Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
           Text("超时时间为300秒:")
             .fontSize(14)
             .width(130)
             .flexGrow(0)
          Text("300000")
             .width(110)
             .fontSize(12)
             .flexGrow(1)
          Button("连接测试")
             .onClick(() => {
               this.connect2Server(false, 300000)
             })
             .width(110)
             .fontSize(14)
             .flexGrow(0)
         }
         .width('100%')
         .padding(5)
        Scroll(this.scroller) {
           Text(this.msgHistory)
             .textAlign(TextAlign.Start)
             .padding(5)
             .width('100%')
             .backgroundColor(0xeeeeee)
         }
         .align(Alignment.Top)
         .backgroundColor(0xeeeeee)
         .height(300)
         .flexGrow(1)
         .scrollable(ScrollDirection.Vertical)
         .scrollBar(BarState.On)
         .scrollBarWidth(20)
       }
       .width('100%')
       .justifyContent(FlexAlign.Start)
       .height('100%')
       .padding(5)
     }
     .height('100%')
   }
  //连接服务端
   async connect2Server(defaultTimeout: boolean, timeout: number) {
     //执行TCP通讯的对象
     let tcpSocket = socket.constructTCPSocketInstance();
let localAddress = { address: "0.0.0.0", family: 1 }
await tcpSocket.bind(localAddress)
    //服务端地址
     let serverAddress = { address: this.serverIp, port: this.serverPort, family: 1 }
    let option: socket.TCPConnectOptions = { address: serverAddress }
     if (!defaultTimeout) {
       option = { address: serverAddress, timeout: timeout }
       this.msgHistory += "连接超时时间设置:" + timeout.toString() + "\r\n";
     } else {
       this.msgHistory += "连接超时时间设置:default" + "\r\n";
     }
    this.msgHistory += "连接开始时间:" + await  getCurrentTimeString() + "\r\n";
     await tcpSocket.connect(option)
       .then(() => {
         this.msgHistory += 'connect success ' + "\r\n";
       })
       .catch(async (e) => {
         this.msgHistory += 'connect fail ' + e.message + "\r\n";
         this.msgHistory += "连接结束时间:" + await getCurrentTimeString() + "\r\n\r\n";
       })
    await tcpSocket.close()
   }
 }
//同步获取当前时间的字符串形式
 async function getCurrentTimeString() {
   let time = ""
   await  systemDateTime.getDate().then(
     (date) => {
       time = date.getHours().toString() + ":" + date.getMinutes().toString()
       + ":" + date.getSeconds().toString() + ":" + date.getMilliseconds().toString()
     }
   )
   return "[" + time + "]"
 }
步骤4:编译运行,可以使用模拟器或者真机。
步骤5:配置服务端IP和端口,一定要设置不存在的地址,然后逐次单击“连接测试”按钮,执行后的截图如下所示:

截图的最后是连接日志信息:

3.TCP连接超时分析
从输出的日志可以分析如下:
1.默认的超时时间为5秒钟
2.超时时间设置为0时,按照5秒钟计算超时时间
3.设置3秒钟或者30秒钟,实际超时时间就是3秒钟或者30秒钟
4.设置大于65秒的超时时间,实际超时时间为65秒左右
前3个好理解,最后这个65秒是怎么回事呢?这里分析一下,实际上,TCP连接重试时执行等待时间翻倍的规则,也就是连接失败后等待1秒钟重试,再失败等待2秒钟,然后依次是4秒钟、8秒钟、16秒钟、32秒钟,linux默认重试5次,也就是1+2+4+8+16+32=63秒钟,再加上其他耗费的时间,所以表现出来最大超时时间是65秒左右。
怎么样,是不是对鸿蒙系统下TCP连接超时时间有了更清晰的认识呢?
(本文作者原创,除非明确授权禁止转载)
本文码云源码地址:https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/tcp/TCPTimeoutDemo
本系列码云源码地址:
https://gitee.com/zl3624/harmonyos_network_samples
  
