我们知道,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数据流的多线程处理。

基于libnids的TCP数据流的还原(多线程实现) .的更多相关文章

  1. ZooKeeper(四):从TCP数据流到zk内部处理包的转换

    通过前面几篇文章,我们可以从整体上看到zk是如何处理网络数据的宏观架构. 本文我们从细节着手,看一下一个tcp的包是如何转换到内部的数据流处理的. 一.监听用户请求socket 基于NIO的端口监听, ...

  2. 【Java TCP/IP Socket】基于NIO的TCP通信(含代码)

    NIO主要原理及使用 NIO采取通道(Channel)和缓冲区(Buffer)来传输和保存数据,它是非阻塞式的I/O,即在等待连接.读写数据(这些都是在一线程以客户端的程序中会阻塞线程的操作)的时候, ...

  3. 基于Linux的TCP网络聊天室

    1.实验项目名称:基于Linux的TCP网络聊天室 2.实验目的:通过TCP完成多用户群聊和私聊功能. 3.实验过程: 通过socket建立用户连接并传送用户输入的信息,分别来写客户端和服务器端,利用 ...

  4. 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载

    一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...

  5. 用C#基于WCF创建TCP的Service供Client端调用

    本文将详细讲解用C#基于WCF创建TCP的Service供Client端调用的详细过程 1):首先创建一个Windows Service的工程 2):生成的代码工程结构如下所示 3):我们将Servi ...

  6. 基于.NET Socket Tcp的发布-订阅框架

    基于.NET Socket Tcp的发布-订阅框架 一.分布式消息总线 在很多MIS项目之中都有这样的需求,需要一个及时.高效的的通知机制,即比如当使用者A完成了任务X,就需要立即告知使用者B任务X已 ...

  7. 基于“泵”的TCP通讯(接上篇)

    基于“泵”的TCP通讯(接上篇) 上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的 ...

  8. TCP/IP具体解释学习笔记--TCP数据流

    1.TCP的交互数据流 (1)基本概念 所谓交互数据流,其对TCP而言,就是他们所产生的大多数的TCP报文段中所包括的数据不超过10个字节.比如聊天等telnet的软件的TCP数据流就属于TCP交互数 ...

  9. 基于libuv的TCP设计(三)

      基于libuv的TCP设计(一) 基于libuv的TCP设计(二)   一.第二版本的libuv_tcp已经基本可以使用.不会出错与崩溃现象,支持几百路客户端同时连接.可是有一缺陷就占用CPU非常 ...

随机推荐

  1. 多线程学习笔记八之线程池ThreadPoolExecutor实现分析

    目录 简介 继承结构 实现分析 ThreadPoolExecutor类属性 线程池状态 构造方法 execute(Runnable command) addWorker(Runnable firstT ...

  2. Linux驱动之USB(个人)

                              USB概述 <USB简介> a:背景 USB是Universal Serial Bus的缩写,是一种全新的,双向同步传输的,支持热插拔的 ...

  3. android studio svn 创建分支

    创建分支或标签 从哪里复制 工作副本 用这个变体去创建分支,并带着当地的改变.通常,服务项将被 添加带历史 , 不仅仅只有目标目录. 每个不同于根的版本文件 ,将被指定的复制.它推荐 去更新 工作副本 ...

  4. codevs 1086 栈 2003年NOIP全国联赛普及组

    题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). ...

  5. UVA.11427.Expect the Expected(期望)

    题目链接 \(Description\) https://blog.csdn.net/Yukizzz/article/details/52084528 \(Solution\) 首先每一天之间是独立的 ...

  6. 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

    Solution 注意取模!!! Code #include<bits/stdc++.h> #define mod 1000000007 #define LL long long usin ...

  7. Android 获取手机信息,设置权限,申请权限,查询联系人,获取手机定位信息

    Android 获取手机信息,设置权限,申请权限,查询联系人,获取手机定位信息 本文目录: 获取手机信息 设置权限 申请权限 查询联系人 获取手机定位信息 调用高德地图,设置显示2个坐标点的位置,以及 ...

  8. ant design的一些坑

    1.在本地修改ant design的某些样式可以生效,但在线上就失效了.比如collapse组件里的箭头图标在本地和在线上的类名有变化,本地类名,线上类名:箭头图标的svg样式在线上会自动添加一个内联 ...

  9. centos ssh终端下高亮显示git分支名

    #set git branch green=$'\e[1;32m' magenta=$'\e[1;35m' normal_colours=$'\e[m' function find_git_branc ...

  10. Android应用程序模型:应用程序,任务,进程,线程

    大多数操作系统,在应用程序所寄存的可执行程序映像(如Windows系统里的.exe).它所运行的进程以及和用户交互的图标和应用之间有一种严格的1对1关系.在Android系统里,这些关联要松散得多.并 ...