libNids TCP 分析

来源:互联网 发布:解不定积分软件 编辑:程序博客网 时间:2024/05/22 17:39

1. 使用场景

在一大流量网络中心旁路抓包,不能完全排除乱序或丢包的可能

2. Review代码

2.1 窗口检验部分代码

  if (    ! (  !datalen && ntohl(this_tcphdr->th_seq) == rcv->ack_seq  )    && /* zero window handle */    ( !before(ntohl(this_tcphdr->th_seq), rcv->ack_seq + rcv->window*rcv->wscale) ||          before(ntohl(this_tcphdr->th_seq) + datalen, rcv->ack_seq)          )      ) {      return;  }

上面的这串代码有很大问题,如果TCP正常交互可能会没太大的问题,但一旦有异常就会造成重组后的流不完整,甚至无法重组。

2.2 四次挥手部分代码

  if ((this_tcphdr->th_flags & TH_ACK)) {    handle_ack(snd, ntohl(this_tcphdr->th_ack));    if (rcv->state == FIN_SENT)      rcv->state = FIN_CONFIRMED;    if ((rcv->state == FIN_CONFIRMED && snd->state == FIN_CONFIRMED) ||        (rcv->state == FIN_CONFIRMED && snd->state == TCP_CLOSING)) {      struct lurker_node *i;      a_tcp->nids_state = NIDS_CLOSE;      for (i = a_tcp->listeners; i; i = i->next)          (i->item) (a_tcp, &i->data);      nids_free_tcp_stream(tcp, a_tcp);      return;    }  }

上面这部分代码是处理 TCP关闭的,需要四次正确挥手才能走到这个逻辑里,如果在一方出现异常,会在他处将其中的状态置为 TCP_CLOSING 所以在这还需要加入这个判断。

还有个问题,Android 系统部分APP使用的是三次挥手,此时还需在process_tcp 后面对三次挥手的进行判断,一时出现三次挥手即可关闭TCP,无需等待最后一个ack

2.2 内存增长

在TCP会造成内存快速增长的原因大致如下
* 如有丢包情况造成大量缓存包,如迟迟未补上所需报文将会愈演愈烈
* 上层数据要对 IP 数据包进行检验,看是否有IP分片,如果你的业务是基于TCP重组后的数据的话,请一定要做IP分片对系统影响的测试,否则一条TCP流就会被丢弃,64K的缓冲数据也会造成内存增加
* TCP 本身具有结点池,但其本身的池会按照分配的时间进行老化,建议在每个TCP流来新包的时候更新下顺序,只需要将当前结点取出放置在最前端即可(TCP结点为双向链表,效率不是问题)强烈建议

3. 总结

先写这么多,这里还有好多需要待完善,关键要看你的运用场景,对TCP重组有多大的要求,是否允许丢包等等。在现行情况下,技术是为业务服务的,所以一定想清你的业务需要怎样的TCP流。

0 0