基于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数据流的多线程处理。

你可能感兴趣的:(多线程,tcp,struct,function,null,buffer)