zoukankan      html  css  js  c++  java
  • TCP close seq问题

    测试mt_hls一条流时,发现会话的时长总是对应不上。

    仔细观察发现:

    注意

      1.包1735 (客户端) 发送FIN 请求,seq = 2435582428

      2.包1736,1737,1738 (服务端)继续传输数据

         3.包1739服务端 回传 对 1735包 FIN 的ack 。 recv_ack =2435582429

         4.包1740 (客户端)发送 RST,seq = 2435582428, 这是不对的! seq应该 = 2435582429 故 包异常。

         5.包2319 (客户端)继续发送RST,seq= 2435582429, 此时包正常。 故此时的会话结束时间 记录为此刻的FRAME 的 echo time.

    附:tcp.c process_tcp 1228行附近

     if (
          ! (  !datalen && ntohl(this_tcphdr->th_seq) == rcv->ack_seq  )
          &&
          ( !before(ntohl(this_tcphdr->th_seq), rcv->ack_seq + rcv->window*rcv->wscale) ||
              before(ntohl(this_tcphdr->th_seq) + datalen, rcv->ack_seq)  
            )
         )  
          {
              printf("----> :%u + %d , %u 
    ",ntohl(this_tcphdr->th_seq), datalen,  rcv->ack_seq);
         return;
          }
    
      if ((this_tcphdr->th_flags & TH_RST)) {
        if (a_tcp->nids_state == NIDS_DATA) {
          struct lurker_node *i;
    
                printf("tcp_close NIDS_RESET time: %lf, ack:%u
    ", a_tcp->latest_tv.tv_sec + a_tcp->latest_tv.tv_usec / 1000000.0, a_tcp->client.ack_seq);
    
          a_tcp->nids_state = NIDS_RESET;
          for (i = a_tcp->listeners; i; i = i->next)
        (i->item) (a_tcp, &i->data);
        }
        nids_free_tcp_stream(a_tcp);
        return;
      }

    此代码片段 是做一个seq检验的。

    1. 包1740
    ! ( !datalen && ntohl(this_tcphdr->th_seq) == rcv->ack_seq )

    包1740 当前datalen 为0 且 th_seq (2435582428) 不等于 rcv->ack_seq(2435582429).

    且 before(ntohl(this_tcphdr->th_seq) + datalen, rcv->ack_seq), 2435582428 + 0 < 2435582429 成立

    此包丢弃。

    2.包2319

    此时TCP会话置为 NIDS_RESET状态, 关闭会话。



    注:
    序列号为当前端成功发送的数据位数,确认号为当前端成功接收的数据位数,SYN标志位和FIN标志位也要占1位

    序列号和确认号

    TCP会话的每一端都包含一个32位(bit)的序列号,该序列号被用来跟踪该端发送的数据量。每一个包中都包含序列号,在接收端则通过确认号用来通知发送端数据成功接收

    当某个主机开启一个TCP会话时,他的初始序列号是随机的,可能是0和4,294,967,295之间的任意值,然而,像Wireshark这种工具,通常显示的都是相对序列号/确认号,而不是实际序列号/确认号,相对序列号/确认号是和TCP会话的初始序列号相关联的。这是很方便的,因为比起真实序列号/确认号,跟踪更小的相对序列号/确认号会相对容易一些

    比如,在“包1”中,最初的相对序列号的值是0,但是最下方面板中的ASCII码显示真实序列号的值是0xf61c6cbe,转化为10进制为4129057982

    如果想要关闭相对序列号/确认号,可以选择Wireshark菜单栏中的 Edit -> Preferences ->protocols ->TCP,去掉Relative sequence number后面勾选框中的√即可



    参考:http://blog.csdn.net/a19881029/article/details/38091243
    http://blog.csdn.net/whuslei/article/details/6667471



  • 相关阅读:
    Java比较两个对象的不同之处
    windows下MongoDB的安装及配置
    springboot对应的springcloud版本
    Spring注解 @Scope 详解
    https HttpUtils 绕过证书
    thymeleaf 基本使用
    java8 groupby 对多个字段进行去重, 统计 partitioningBy
    linux硬件数据
    Nginx referer防盗链模块
    Nginx HTTP 过滤addition模块(响应前后追加数据)
  • 原文地址:https://www.cnblogs.com/iclk/p/4540292.html
Copyright © 2011-2022 走看看