#include ".\NetCommuication\commuanalyzer.h"
class CSzBinaryAnalyzer :
public CCommuAnalyzer
{
public:
CSzBinaryAnalyzer(void);
~CSzBinaryAnalyzer(void);
/*
* Desc:
* 依据输入的业务报文,打包成网络报文并输出
* 默认的通讯分析器只含简单的网络层组包解包逻辑逻辑,不包含对于业务协议的包。网络包规则如下:
* 网络包头包括:包头识别码(换行回车符:'\n\r')+ 一个整型值的长度,无包尾
* 注:当符合以下条件的情况下可以不调用该接口
* 1、业务报文件长度小于 TCPConnect中定义的:最大网络接收缓冲区大小
* 2、对网络包组包规则无特殊要求
* Pram:
* pszBodyIn 业务报文
* iBodyLenIn 业务报文长度
* pszNetBufOut 网络报文 【输出参数由调用者清除】
* iBufLenOut 网络报文长度
* Retr:
* bool 打包成功返回 true, 打包失败返回 false
*/
virtual bool PackNetPackage(char* pszBodyIn, int iBodyLenIn, char*& pszNetBufOut, int& iBufLenOut);
/*
* Desc:
* 依据输入的网络接收缓冲区,判断是否存在脏数据需要被清理,并通过返回值iSkipLen告知需要被处理的脏数据长度。
* 必须实现存在错误包时的应对处理,由(-1:抛弃错误数据,但不断开网络;-2:中断网络)
*
* Pram:
* pszNetRcvBufIn 网络接收缓冲区
* iNetRcvBufLenIn 网络接收缓冲区长度
* iSkipLen 网络接收缓冲区超始位置开始需要被忽略的脏数据长度, 必须正确,否则会导致清楚正确的数据
* Retr:
* int 0:无脏数据 -1:有脏数据但不中断网络, -2:有脏数据需要中断网络
*/
virtual int IsExistDirtyData(char* pszNetRcvBufIn, int iNetRcvBufLenIn, int& iSkipLen);
/*
* Desc:
* 依据输入的网络接收缓冲区,判断是否存在完整的网络包
*
* Pram:
* pszNetRcvBufIn 网络接收缓冲区
* iNetRcvBufLenIn 网络接收缓冲区长度
* Retr:
* bool true:有完整网络报文; false:无完整网络报文
*/
virtual bool IsHasFullPackage(char* pszNetRcvBufIn, int iNetRcvBufLenIn);
/*
* Desc:
* 依据输入的网络接收缓冲区,解包出第一个完整业务报文输出
* 在调用该函数之前,必须先调用 IsHasFullPackage(...),且返回值必须为0
* Pram:
* pszNetRcvBufIn 网络接收缓冲区
* iNetRcvBufLenIn 网络接收缓冲区长度
* pszBodyOut 完整的业务报文 【输出参数,由应用(CommuApplication)负责删除】
* iBodyLenOut 业务报文长度(即网络报文体)
* iHeadLenOut 网络报文头长度
* iTailLenOut 网络报文尾长度
* Retr:
* bool 解包成功返回 true, 解包失败返回 false
*/
virtual bool UnpackNetPackage(char* pszNetRcvBufIn, int iNetRcvBufLenIn, char*& pszBodyOut, int& iBodyLenOut, int& iHeadLenOut, int& iTailLenOut);
};
#include "StdAfx.h"
#include "SzBinaryAnalyzer.h"
#include "MessageStructs.h"
#include "CustBinaryBizClass.h"
CSzBinaryAnalyzer::CSzBinaryAnalyzer(void)
{
this->m_iNetPackHeadLen = sizeof(BINARY::HEAD);
this->m_iNetPackTailLen = sizeof(BINARY::TAIL);
}
CSzBinaryAnalyzer::~CSzBinaryAnalyzer(void)
{
}
/*
* Desc:
* 依据输入的业务报文,打包成网络报文并输出
* 默认的通讯分析器只含简单的网络层组包解包逻辑逻辑,不包含对于业务协议的包。网络包规则如下:
* 网络包头包括:包头识别码(换行回车符:'\n\r')+ 一个整型值的长度,无包尾
* 注:当符合以下条件的情况下可以不调用该接口
* 1、业务报文件长度小于 TCPConnect中定义的:最大网络接收缓冲区大小
* 2、对网络包组包规则无特殊要求
* Pram:
* pszBodyIn 业务报文
* iBodyLenIn 业务报文长度
* pszNetBufOut 网络报文 【输出参数由调用者清除】
* iBufLenOut 网络报文长度
* Retr:
* bool 打包成功返回 true, 打包失败返回 false
*/
bool CSzBinaryAnalyzer::PackNetPackage(char* pszBodyIn, int iBodyLenIn, char*& pszNetBufOut, int& iBufLenOut)
{
bool bReturn = false;
iBufLenOut = iBodyLenIn;
pszNetBufOut = new char[iBufLenOut+1];
if (pszNetBufOut == NULL)
{
// std::cout<< "分配内存存储打包后的网络报文失败" << std::endl;
}
else
{
memset(pszNetBufOut, 0x00, iBufLenOut+1);
memcpy(pszNetBufOut, pszBodyIn, iBodyLenIn);
}
bReturn = true;
return bReturn;
}
/*
* Desc:
* 依据输入的网络接收缓冲区,判断是否存在脏数据需要被清理,并通过返回值iSkipLen告知需要被处理的脏数据长度。
* 必须实现存在错误包时的应对处理,由(-1:抛弃错误数据,但不断开网络;-2:中断网络)
*
* Pram:
* pszNetRcvBufIn 网络接收缓冲区
* iNetRcvBufLenIn 网络接收缓冲区长度
* iSkipLen 网络接收缓冲区超始位置开始需要被忽略的脏数据长度, 必须正确,否则会导致清楚正确的数据
* Retr:
* int 0:无脏数据 -1:有脏数据但不中断网络, -2:有脏数据需要中断网络
*/
int CSzBinaryAnalyzer::IsExistDirtyData(char* pszNetRcvBufIn, int iNetRcvBufLenIn, int& iSkipLen)
{
int iReturn = 0;
if (iNetRcvBufLenIn > m_iNetPackHeadLen)
{
unsigned int uiBodyLength = ::ntohl(((BINARY::HEAD*)pszNetRcvBufIn)->BodyLength);
if (iNetRcvBufLenIn >= ((int)uiBodyLength + m_iNetPackHeadLen + m_iNetPackTailLen))
{
unsigned iCheckSum = ::ntohl(((BINARY::TAIL*)(pszNetRcvBufIn + uiBodyLength + m_iNetPackHeadLen))->CheckSum);
// if (::ntohl(((BINARY::HEAD*)pszNetRcvBufIn)->MsgType) == BINARY::MsgType_Logon1)
// {
// BINARY::CLogon logon;
// int ilogonLen = logon.GetMessageSize();
// logon.Deserialize(pszNetRcvBufIn, uiBodyLength+ m_iNetPackHeadLen + m_iNetPackTailLen);
// int iMessageLen = 0;
// int IheartBeat = logon.GetLOGINHeartBtInt();
// unsigned iCheckSumCmp = BINARY::GenerateCheckSum(logon.Serialize(iMessageLen), uiBodyLength+ m_iNetPackHeadLen);
// }
unsigned iCheckSumCmp = BINARY::GenerateCheckSum(pszNetRcvBufIn, uiBodyLength+ m_iNetPackHeadLen);
if (iCheckSum != iCheckSumCmp)
{
iReturn = -2;
}
}
}
return iReturn;
}
/*
* Desc:
* 依据输入的网络接收缓冲区,判断是否存在完整的网络包
*
* Pram:
* pszNetRcvBufIn 网络接收缓冲区
* iNetRcvBufLenIn 网络接收缓冲区长度
* Retr:
* bool true:有完整网络报文; false:无完整网络报文
*/
bool CSzBinaryAnalyzer::IsHasFullPackage(char* pszNetRcvBufIn, int iNetRcvBufLenIn)
{
bool bReturn = false;
unsigned int uiBodyLength = ::ntohl(((BINARY::HEAD*)pszNetRcvBufIn)->BodyLength );
if ( iNetRcvBufLenIn >= ((int)uiBodyLength+ m_iNetPackHeadLen + m_iNetPackTailLen ) )
{
bReturn = true;
}
return bReturn;
}
/*
* Desc:
* 依据输入的网络接收缓冲区,解包出第一个完整业务报文输出
* 在调用该函数之前,必须先调用 IsHasFullPackage(...),且返回值必须为true
* Pram:
* pszNetRcvBufIn 网络接收缓冲区
* iNetRcvBufLenIn 网络接收缓冲区长度
* pszBodyOut 完整的业务报文 【输出参数,由应用(CommuApplication)负责删除】
* iBodyLenOut 业务报文长度(即网络报文体)
* iHeadLenOut 网络报文头长度
* iTailLenOut 网络报文尾长度
* Retr:
* bool 解包成功返回 true, 解包失败返回 false
*/
bool CSzBinaryAnalyzer::UnpackNetPackage(char* pszNetRcvBufIn, int iNetRcvBufLenIn, char*& pszBodyOut, int& iBodyLenOut, int& iHeadLenOut, int& iTailLenOut)
{
bool bReturn = false;
unsigned int uiBodyLength = ::ntohl(((BINARY::HEAD*)pszNetRcvBufIn)->BodyLength);
if (iNetRcvBufLenIn >= ((int)uiBodyLength+ m_iNetPackHeadLen + m_iNetPackTailLen))
{
iBodyLenOut = uiBodyLength+ m_iNetPackHeadLen + m_iNetPackTailLen;
pszBodyOut = new char[iBodyLenOut + 1];
if (pszBodyOut == NULL) {
// std::cout<< "分配内存存储解包后的业务报文失败" << std::endl;
}
else {
memset(pszBodyOut, 0x00, iBodyLenOut + 1);
memcpy(pszBodyOut, pszNetRcvBufIn, iBodyLenOut);
bReturn = true;
}
}
return bReturn;
}