• 基于libnids的TCP数据流的还原(多线程实现) .


    我们知道,libnids本身可以实现TCP数据流的重组,但是如果一个TCP流数据量比较大的时候,就会分成好多个TCP报文段,这些报文段在网络中的传播可能是乱序的,利用libnids可以帮助我们按顺序接收到这些报文段,即实现TCP报文段的重组。

        但是我们如何把这些顺序的报文段重新还原成一个完整的数据文件,也是要考虑的一个问题,因为在很多时候,单个的报文段对我们的意义不大,我们需要一个完整的数据,这样才有助于我们进一步分析网络中的数据内容。

        下面的程序实现了基于libnids的TCP数据流的还原,我使用了多线程来控制数据的处理,主要的数据结构是一个带头结点的双向链表队列,队列中的每个结点存储一个完整的TCP数据流的内容,另外还有两个元素,分别是指向前导和后续结点的结构体指针。结构体定义如下:

        struct buf{

            char *buffer;

            struct buf *prev;

            struct buf *next;

        };

        头结点:  struct buf *head;

        多线程对该链表的操作:

        向链表中放数据:void put_function(int size, char *data)

                        {

                              pthread_mutex_lock(&mutex);

                              meke_new_item(size, data);

                              buffer_has_item++;

                              pthread_mutex_unlock(&mutex);

                              sleep(1);

                        }

        mutex为互斥锁,size为data的大小,data为完整的数据流,buffer_has_item为当前链表中结点的数目。

        从链表中去数据的操作:(这是一个线程函数,在执行pthread_create是创建)

        void get_function(void)

        {

              while(1){

                      pthread_mutex_lock(&mutex);

                      if(buffer_has_item > 0){

                               consume_item();

                               buffer_has_item--;

                      }

                      pthread_mutex_unlock(&mutex);

                      sleep(1);

              }

        }

        创建新的节点并把它挂到队列当中:

        void make_new_item(int size, char *data)

        {

              struct buf *con;

              if(!(con = (struct buf *)malloc(sizeof(struct buf)))){

                     assert("con malloc fail!");

              }

              if(!(con->buffer = (char *)malloc(size*sizeof(char)))){

                      assert("con buffer malloc fail!");

              }

              memset(con->buffer, 0, size*sizeof(char));

              memcpy(con->buffer, data, size*sizeof(char));

              con->prev = NULL;

              con->next = NULL;

              if(head->next == NULL){

                    head->next = con;

                    head->prev = con;

                    con->prev = head;

              }else{

                    con->prev = head->prev;

                    head->prev->next = con;

                    head->prev = con;

                    con->next = NULL;

              }

         }

         处理还原之后的数据:

         void consume_item()

         {

              int k;

              struct buf *p;

              if(head->next){

                    

                     printf("%s", head->next->buffer);

                     p = head->next;

                     if(head->next->next){

                           head->next = head->next->next;

                           head->next->preb = head;

                     }else{

                            head->next = NULL;

                            head->prev = NULL;

                      }

                      if(p){

                            free(p);

                            p = NULL;

                       }

               }

         }

         链表初始化(可以把整个程序的初始化都放在这里进行):

         void init_dlink()

         {

               if(!(head = (struct buf *)malloc(sizeof(struct buf)))){

                         assert("head malloc fail!");

                }

                head->next = NULL;

                head->prev = NULL;

          }

          head的定义是一个全局变量,struct buf *head;

          在主函数当中,要创建线程,注册libnids回调函数:

          int main(int argc, char *argc[])

          {

                pthread_t thread;

                init_dlink();

                pthread_mutex_init(&mutex, NULL);

                if(!nids_init())P{

                      assert("nids init fail!");

                }

                pthread_create(&thread, NULL, (void *)get_function, NULL);

                nids_register_tcp(tcp_protocol_callback);

                nids_tun();

                return 0;

           }

           在回调函数当中,我们可以组织实现TCP数据流的还原,并把还原之后的数据添加到链表当中:

           void tcp_protocol_callback(struct tcp_stream *tcp_connection, void **arg)

           {

                switch(tcp_connection->nids_state){

                       .....................

                       case NIDS_DATA:{

                             ................

                             if(tcp_connection->client.count_new){

                                   

                                    ..............

                                   

                                    put_function(sum_len, content);

                             }

                       }

                }

            }

        至此,就完成了还原TCP数据流的多线程处理。

  • 相关阅读:
    【BZOJ5416】【NOI2018】冒泡排序(动态规划)
    【BZOJ4832】抵制克苏恩(矩阵快速幂,动态规划)
    【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
    【BZOJ3142】[HNOI2013]数列(组合计数)
    【BZOJ3925】[ZJOI2015]地震后的幻想乡(动态规划)
    【Luogu4707】重返现世(min-max容斥)
    【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)
    【APIO2018】铁人两项(圆方树,动态规划)
    【BZOJ4005】[JLOI2015] 骗我呢(容斥,组合计数)
    【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
  • 原文地址:https://www.cnblogs.com/rainbowzc/p/3600277.html
Copyright © 2020-2023  润新知