测试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