C++版的网络数据包解析策略(升级版)

初版:http://www.cnblogs.com/wjshan0808/p/6580638.html

说明:在实现了对应的接口后该策略可以适合绝大多数的网络数据包结构

首先,是三个接口

IProduceProxy.h

#ifndef _I_PRODUCE_PROXY_H_
#define _I_PRODUCE_PROXY_H_

//Code
#define    CODE_PRODUCE_PROXY_OK        0x00    //OK
#define CODE_PRODUCE_PROXY_NI        0x01    //Not Implemented
#define CODE_PRODUCE_PROXY_NT        0x02    //Nothing
#define CODE_PRODUCE_PROXY_RY        0x0F    //Ready 

//INTERFACE
class CIProduceProxy
{
public:
    virtual int ProduceProxy(char* &szBuffer, int &nBufferLength) = 0;
};

//PFN
typedef    int(CIProduceProxy::*PFN_PRODUCEPROXY)(char* &szBuffer, int &nBufferLength);

#endif //_I_PRODUCE_PROXY_H_

IStrategyProtocol.h

#ifndef _I_STRATEGY_PROTOCOL_H_
#define _I_STRATEGY_PROTOCOL_H_

//CODE
#define CODE_STRATEGY_PROTOCOL_OK        0x00        //OK
#define CODE_STRATEGY_PROTOCOL_NI        0x01        //Not Implemented
#define CODE_STRATEGY_PROTOCOL_ML        0x02        //Miss Length
#define CODE_STRATEGY_PROTOCOL_RY        0x0F        //Ready

//INTERFACE
class CIStrategyProtocol
{
public:
    virtual int ExtractLength(const char* szBuffer, int nBufferLength, int &nExtractLength) = 0;
};

//PFN
typedef    int    (CIStrategyProtocol::*PFN_STRATEGYPROTOCOL)(const char* szBuffer, int nBufferLength, int &nExtractLength);

#endif //_I_STRATEGY_PROTOCOL_H_

IConsumeProxy.h

#ifndef _I_CONSUME_PROXY_H_
#define _I_CONSUME_PROXY_H_

//Code
#define    CODE_CONSUME_PROXY_OK        0x00    //OK
#define CODE_CONSUME_PROXY_NI        0x01    //Not Implemented
#define CODE_CONSUME_PROXY_RY        0x0F    //Ready

//INTERFACE
class CIConsumeProxy
{
public:
    virtual int ConsumeProxy(const char* szBuffer, int nBufferLength) = 0;
};

//PFN
typedef    int(CIConsumeProxy::*PFN_CONSUMEPROXY)(const char* szBuffer, int nBufferLength);

#endif //_I_CONSUME_PROXY_H_

然后,例如我们有如下一个协议对象,实现IStrategyProtocol接口

.h

#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_

#include "IStrategyProtocol.h"

class CProtocol : public CIStrategyProtocol
{
public:
    CProtocol();
    ~CProtocol();

public:
    int ExtractLength(const char* szBuffer, int nBufferLength, int &nExtractLength) override;

};

#endif //_PROTOCOL_H_

.cpp

#include "Protocol.h"

CProtocol::CProtocol()
{
}
CProtocol::~CProtocol()
{
}

int CProtocol::ExtractLength(const char* szBuffer, int nBufferLength, int &nExtractLength)
{
    nExtractLength = 0;

    if (false)
        return CODE_STRATEGY_PROTOCOL_ML;

    //...

    return CODE_STRATEGY_PROTOCOL_OK;
}
 

其次,例如我们有如下的网络端对象,实现IProduceProxy,IConsumeProxy接口
.h

#ifndef _NET_CLIENT_H_
#define _NET_CLIENT_H_

#include "ExtractTask.h"
#include "Protocol.h"

class CNetClient : public CIProduceProxy, public CIConsumeProxy
{
public:
    CNetClient();
    ~CNetClient();

public:
    int Init();
    int Receive(char* szReceiveBuffer, int nBufferLength);
    int Processing(const char* szData, int nDataLength);

public:
    int ProduceProxy(char* &szBuffer, int &nBufferLength) override;
    int ConsumeProxy(const char* szBuffer, int nBufferLength) override;

private:
    CExtractTask* m_pExtractor;
    CProtocol* m_pProtocol;
};

#endif //_DRIVE_M_40064900_H_

.cpp

#include "NetClient.h"

CNetClient::CNetClient()
{
    m_pProtocol = new CProtocol();
    m_pExtractor = new CExtractTask();
}
CNetClient::~CNetClient()
{
}

int CNetClient::Init()
{
    m_pExtractor->Proxies(this, this->m_pProtocol, this);

    return 0;
}

int CNetClient::ProduceProxy(char* &szBuffer, int &nBufferLength)
{
    nBufferLength = Receive(szBuffer, nBufferLength);
    if (nBufferLength <= 0)
        return CODE_PRODUCE_PROXY_NT;
    return CODE_PRODUCE_PROXY_OK;
}

int CNetClient::ConsumeProxy(const char* szBuffer, int nBufferLength)
{
    Processing(szBuffer, nBufferLength);
    return CODE_CONSUME_PROXY_OK;
}
 

最终是我们的解析策略实现对象
.h

#ifndef _EXTRACT_TASK_H_
#define _EXTRACT_TASK_H_

#include "IStrategyProtocol.h"
#include "IProduceProxy.h"
#include "IConsumeProxy.h"

class CExtractTask
{
public:
    CExtractTask();
    virtual ~CExtractTask();

public:
    int Proxies(CIProduceProxy* pProducer, CIStrategyProtocol* pStrategy, CIConsumeProxy* pConsumer);
    //int Proxies(PFN_PRODUCEPROXY pfnProducer, PFN_STRATEGYPROTOCOL pfnStrategy, PFN_CONSUMEPROXY pfnConsumer);

protected:
    virtual int ProduceImply(char* &szBuffer, int &nBufferLength);
    virtual int StrategyImply(const char* szBuffer, int nBufferLength, int &nExtractLength);
    virtual int ConsumeImply(const char* szExtractCopier, int nExtractLength);

private:
    int Extractor();

private:
    CIProduceProxy*        m_pProducer;
    //PFN_PRODUCEPROXY    m_pfnProducer;
    CIStrategyProtocol*        m_pStrategy;
    //PFN_STRATEGYPROTOCOL    m_pfnStrategy;
    CIConsumeProxy*        m_pConsumer;
    //PFN_CONSUMEPROXY    m_pfnConsumer;
};

#endif //_EXTRACT_TASK_H_

.cpp

#include "ExtractTask.h"
#include <cstring>
#ifdef WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif //WIN32

#define    TIME_BASE_UNIT_VALUE        1000
#define TIME_TASK_SLEEP_16MS        16
#ifdef WIN32
#define    TIME_EXTRACT_8MS        8
#else
#define    TIME_EXTRACT_8MS        (8 * TIME_BASE_UNIT_VALUE)
#endif // WIN32

#define LENGTH_EXTRACT_BUFFER        (1024 * 4)    //接收缓冲区大小 

using namespace std;

CExtractTask::CExtractTask() :
m_pProducer(NULL), m_pStrategy(NULL), m_pConsumer(NULL)
//, m_pfnProducer(NULL), m_pfnStrategy(NULL), m_pfnConsumer(NULL)
{
}
CExtractTask::~CExtractTask(void)
{
    /*
    m_pfnProducer = NULL;
    m_pfnStrategy = NULL;
    m_pfnConsumer = NULL;
    */
    /*
    if (m_pProducer != NULL)
        delete m_pProducer;
    if (m_pStrategy != NULL)
        delete m_pStrategy;
    if (m_pConsumer != NULL)
        delete m_pConsumer;
        */
}

int CExtractTask::Proxies(CIProduceProxy* pProducer, CIStrategyProtocol* pStrategy, CIConsumeProxy* pConsumer)
{
    m_pProducer = pProducer;
    m_pStrategy = pStrategy;
    m_pConsumer = pConsumer;

    return 0;
}
/*
int CExtractTask::Proxies(PFN_PRODUCEPROXY pfnProducer, PFN_STRATEGYPROTOCOL pfnStrategy, PFN_CONSUMEPROXY pfnConsumer)
{
    m_pfnProducer = pfnProducer;
    m_pfnStrategy = pfnStrategy;
    m_pfnConsumer = pfnConsumer;

    return 0;
}
*/
int CExtractTask::ProduceImply(char* &szBuffer, int &nBufferLength)
{
    if (m_pProducer == NULL)// && m_pfnProducer == NULL)
        return CODE_PRODUCE_PROXY_NI;

    if (m_pProducer != NULL)
        return m_pProducer->ProduceProxy(szBuffer, nBufferLength);
    //else if (m_pfnProducer != NULL)
    //    return m_pfnProducer(szBuffer, nBufferLength);

    return CODE_PRODUCE_PROXY_RY;
}

int CExtractTask::StrategyImply(const char* szBuffer, int nBufferLength, int &nExtractLength)
{
    if (m_pStrategy == NULL)// && m_pfnStrategy == NULL)
        return CODE_STRATEGY_PROTOCOL_NI;

    if (m_pStrategy != NULL)
        return m_pStrategy->ExtractLength(szBuffer, nBufferLength, nExtractLength);
    //else if (m_pfnStrategy != NULL)
    //    return m_pfnStrategy(szBuffer, nBufferLength, nExtractLength);

    return CODE_STRATEGY_PROTOCOL_RY;
}

int CExtractTask::ConsumeImply(const char* szExtractCopier, int nExtractLength)
{
    if (m_pConsumer == NULL)// && m_pfnConsumer == NULL)
        return CODE_CONSUME_PROXY_NI;

    if (m_pConsumer != NULL)
        return m_pConsumer->ConsumeProxy(szExtractCopier, nExtractLength);
    //else if (m_pfnConsumer != NULL)
    //    return m_pfnConsumer(szExtractCopier, nExtractLength);

    return CODE_CONSUME_PROXY_RY;
}

int CExtractTask::Extractor()
{
    int nSurplusLength = 0;
    char* szExtractCopier = NULL;
    char* szExtractCopyIterator = NULL;
    //Extract Buffer from Product Proxy.
    do
    {
        //Extract Buffer
        char* szExtractBuffer = new char[LENGTH_EXTRACT_BUFFER]();
        //Extract Length
        int nExtractBufferLength = LENGTH_EXTRACT_BUFFER;
        //Productor Proxy
        int nRet = ProduceImply(szExtractBuffer, nExtractBufferLength);
        if (nRet != CODE_PRODUCE_PROXY_OK)
        {
            //LogMessage(LOGLEVEL_DEBUG, "ProduceProxy Return(%d).", nRet);
            delete[] szExtractBuffer;
            break;
        }
        //LogMessage(LOGLEVEL_INFO, "ProduceProxy Extract Buffer-Length(%d).", nExtractBufferLength);

        //Clone Extractor to extract
        char* szExtractor = szExtractBuffer;
        //Begin to Extract by The Rules
        do
        {
            //Surplus Length less than or equal to zero that Means new could be create
            if (nSurplusLength <= 0)
            {
                //Got Extract-Length from RuleProxy(Extract Whole Length)
                int nExtractLength = 0;
                nRet = StrategyImply(szExtractor, nExtractBufferLength, nExtractLength);
                if (nRet != CODE_STRATEGY_PROTOCOL_OK)
                {
                    break;
                }
                //To new that Means variate value is equal between nSurplusLength and nExtractLength.
                nSurplusLength = nExtractLength;

                //Allocate enough space for new
                szExtractCopier = new char[nExtractLength + 1]();
                //Mark Movable Pointer for Copier
                szExtractCopyIterator = szExtractCopier;
            }
            //when ExtractBufferLength is less than SurplusLength that Means Data copy is continue
            if (nExtractBufferLength < nSurplusLength)
            {
                //Doing copy
                memcpy(szExtractCopyIterator, szExtractor, nExtractBufferLength);
                //Move ExtractCopyIterator position
                szExtractCopyIterator += nExtractBufferLength;
                //Cut down SurplusLength
                nSurplusLength -= nExtractBufferLength;
                //Move Extractor position
                szExtractor += nExtractBufferLength;
                //Cut down ExtractBufferLength
                nExtractBufferLength -= nExtractBufferLength;
            }
            else//(nExtractBufferLength >= nSurplusLength)
            {
                //Doing copy
                memcpy(szExtractCopyIterator, szExtractor, nSurplusLength);
                //Move Extractor position
                szExtractor += nSurplusLength;
                //Cut down ExtractBufferLength
                nExtractBufferLength -= nSurplusLength;
                //Move ExtractCopyIterator position
                szExtractCopyIterator += nSurplusLength;
                //Cut down SurplusLength
                nSurplusLength -= nSurplusLength;
                //Package Whole Length
                ConsumeImply(szExtractCopier, (szExtractCopyIterator - szExtractCopier));
                //Clean szExtractCopier
                delete[] szExtractCopier;
                szExtractCopier = NULL;
            }
        } while (nExtractBufferLength > 0);
        //Clean szExtractBuffer
        delete[] szExtractBuffer;

#ifdef WIN32
        Sleep(TIME_EXTRACT_8MS);
#else
        usleep(TIME_EXTRACT_8MS);
#endif // WIN32
    } while (!m_bStopStream);
    //Clean szExtractCopier
    if (szExtractCopier != NULL)
        delete[] szExtractCopier;
    return 0;
}
时间: 2024-12-13 05:51:43

C++版的网络数据包解析策略(升级版)的相关文章

利用原始套接字实现一个简单的采集网络数据包

//利用原始套接字实现一个简单的采集网络数据包,并进行反向解析IP,MAC地址#include <stdio.h>#include <sys/socket.h>#include <unistd.h>#include <sys/types.h>#include <linux/if_ether.h>#include <linux/in.h> #define BUFFER_MAX 2048 int main(int argc, char *

替代WinPcap的新型Windows网络数据包截获软件——NPcap

NPcap是致力于采用Microsoft Light-Weight Filter (NDIS 6)技术对当前最流行的WinPcap工具包进行改进的一个项目.NPcap项目是最初2013年由Nmap网络扫描器项目(创始人Gordon Lyon)和北京大学罗杨博士发起,由Google公司赞助的一个开源项目,遵循MIT协议(与WinPcap一致).NPcap基于WinPcap 4.1.3源码基础上开发,支持32位和64位架构,在Windows Vista以上版本的系统中,采用NDIS 6技术的NPca

LINUX下的远端主机登入 校园网络注册 网络数据包转发和捕获

第一部分:LINUX 下的远端主机登入和校园网注册 校园网内目的主机远程管理登入程序 本程序为校园网内远程登入,管理功能,该程序分服务器端和客户端两部分:服务器端为remote_server_udp.py 客户端分为单播客户端和广播客户端: 单播客户端client_unicast.py 广播客户端client_broadcast.py 1.单播客户端为根据net.info文件中的网络记录遍历目标网段中的所有IP,向其发送UDP封包. net.info中记录了目标网络中的一个样例IP和目标网段的子

网络数据包分析 网卡Offload

http://blog.nsfocus.net/network-packets-analysis-nic-offload/ 对于网络安全来说,网络传输数据包的捕获和分析是个基础工作,绿盟科技研究员在日常工作中,经常会捕获到一些大小远大于MTU值的数据包,经过分析这些大包的特性,发现和网卡的offload特性有关,本文对网卡Offload技术做简要描述. 文章目录 网络分片技术 网卡offload机制 发送模式 接收模式 网卡offload模式的设置 Linux windows 网卡Offload

Linux内核中网络数据包的接收-第一部分 概念和框架

与网络数据包的发送不同,网络收包是异步的的,因为你不确定谁会在什么时候突然发一个网络包给你,因此这个网络收包逻辑其实包含两件事:1.数据包到来后的通知2.收到通知并从数据包中获取数据这两件事发生在协议栈的两端,即网卡/协议栈边界以及协议栈/应用边界:网卡/协议栈边界:网卡通知数据包到来,中断协议栈收包:协议栈栈/应用边界:协议栈将数据包填充socket队列,通知应用程序有数据可读,应用程序负责接收数据.本文就来介绍一下关于这两个边界的这两件事是怎么一个细节,关乎网卡中断,NAPI,网卡poll,

一个最简单的通过WireShark破解SSL加密网络数据包的方法

原文地址: http://article.yeeyan.org/view/530101/444688 一般来说,我们用WireShark来抓取包进行分析是没有多大问题的.但这里有个问题是,如果你碰到的是用SSL/TLS等加密手段加密过的网络数据的时候,往往我们只能束手无策.在过去的话,如果我们拥有的该传输会话的私钥的话我们还是可以将它提供给WireShark来让其对这些加密数据包进行解密的 1. 简介 相信能访问到这篇文章的同行基本上都会用过流行的网络抓包工具WireShark,用它来抓取相应的

用C++实现网络编程,抓取网络数据包的实现方法和介绍

做过网管或协议分析的人一般都熟悉sniffer这个工具,它可以捕捉流经本地网卡的所有数据包.抓取网络数据包进行分析有很多用处,如分析网络是否有网络病毒等异常数据,通信协议的分析(数据链路层协议.IP.UDP.TCP.甚至各种应用层协议),敏感数据的捕捉等.下面我们就来看看在windows下如何实现数据包的捕获. 下面先对网络嗅探器的原理做简单介绍. 嗅探器设计原理 嗅探器作为一种网络通讯程序,也是通过对网卡的编程来实现网络通讯的,对网卡的编程也是使用通常的套接字(socket)方式来进行.但是,

发现新大陆:一个最简单的破解SSL加密网络数据包的方法

1. 简介 相信能访问到这篇文章的同行基本上都会用过流行的网络抓包工具WireShark,用它来抓取相应的网络数据包来进行问题分析或者其他你懂的之类的事情. 一般来说,我们用WireShark来抓取包进行分析是没有多大问题的.但这里有个问题是,如果你碰到的是用SSL/TLS等加密手段加密过的网络数据的时候,往往我们只能束手无策.在过去的话,如果我们拥有的该传输会话的私钥的话我们还是可以将它提供给WireShark来让其对这些加密数据包进行解密的,但这已经是想当年还用RSA进行网络数据加密的年代的

Linux程序设计学习笔记----网络编程之网络数据包拆封包与字节顺序大小端

网络数据包的封包与拆包 过程如下: 将数据从一台计算机通过一定的路径发送到另一台计算机.应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation),如下图所示: 不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据包(packet),在链路层叫做帧(frame).数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理. 上图对应两台计算机在同一网段中的情况,