当前位置:网站首页 > 编程语言 > 正文

本地回环地址用于什么(本地回环地址ping不通)



1. TCP连接超时简介

TCP是面向连接的协议,通过三次握手建立连接,但是,在建立连接的过程中对方有可能没有响应,这时候发起连接的一方会重试,如果重试多次仍然没有响应,就会触发超时,从而导致连接失败,socket的connect方法支持通过参数设置连接超时时间,默认情况下也可以使用缺省的超时时间,那么,问题来了:

    要回答这些问题还不太容易,官方文档也没有给出,下面咱们就自己尝试下,寻找问题的答案。

    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("")

         .width(110)

         .fontSize(12)

         .flexGrow(1)

         Button("连接测试")

         .onClick(() => {

           this.connect2Server(false, )

         })

         .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() + " ";

     } else {

       this.msgHistory += "连接超时时间设置:default" + " ";

     }

      this.msgHistory += "连接开始时间:" + await getCurrentTimeString() + " ";

      await tcpSocket.connect(option)

      .then(() => {

        this.msgHistory += 'connect success ' + " ";

      })

      .catch(async (e) => {

        this.msgHistory += 'connect fail ' + e.message + " ";

        this.msgHistory += "连接结束时间:" + await getCurrentTimeString() + " ";

      })

      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

    到此这篇本地回环地址用于什么(本地回环地址ping不通)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

    版权声明


    相关文章:

  1. seattle英语怎么读(seattle用英语怎么读)2025-01-08 14:27:07
  2. ad20怎么设置中文(ad21设置中文)2025-01-08 14:27:07
  3. 主板nvme接口识别不了(nvme 主板不识别)2025-01-08 14:27:07
  4. 安装权限设置在哪里(vivo手机安装权限设置在哪里)2025-01-08 14:27:07
  5. 跨域步态是指什么意思(跨阈步态是什么步态)2025-01-08 14:27:07
  6. 分层图怎么做出来的(分层图怎么做出来的视频)2025-01-08 14:27:07
  7. 字符串转xml对象(xml字符串转成xml文件)2025-01-08 14:27:07
  8. 返回上一级目录的快捷键(返回上一级文件夹的快捷键)2025-01-08 14:27:07
  9. win10双系统卸载linux(win10卸载linux子系统)2025-01-08 14:27:07
  10. lda主题模型分析结果(lda主题模型困惑度)2025-01-08 14:27:07
  11. 全屏图片