NetComm-CommDefine

#pragma once


#include <winsock2.h>


namespace TCPCONNECT
{
  enum BLOCKING_MODE
  {
    MODE_BLOCKING = 0,
    MODE_UNBLOCKING = 1
  };


  enum COMMUNICATION_MODE
  {
    MODE_SERVER = 1,
    MODE_CLIENT = 2
  };


  enum EVENT_TYPE
  {
    // Client
    CONNECTINT__EVENT        = 0,   // 正在连接
    CONNECT_SUCCESS_EVENT    = 1,   // 连接成功
    CONNECT_FAILD_EVENT      = 2,   // 连接失败
    // Server
    LISTEN_SUCCESS_EVENT     = 5,   // 侦听成功
    LISTEN_FAILD_EVENT       = 6,   // 侦听失败
    CONNECT_GET_IN_EVENT     = 7,   // 连接接入
    CONNECT_QUIT_EVENT       = 8,   // 连接退出
    // SHARE
    CONNECT_BREAKED_EVENT    = 12,  // 断开连接
    RECEIVE_TIMEOUT_EVENT    = 13,  // 数据接收超时


    HAS_DIRTY_DATA_CLEAR     = 51,  // 连接上存在脏数据时,清除掉脏数据
    HAS_DIRTY_DATA_BREAK     = 52   // 连接上存在脏数据时,SOCKET断开
  };


  typedef struct tagConnectInfo
  {
    tagConnectInfo() 
    {
      memset(this, 0x00, sizeof(tagConnectInfo));
    }
    int iSocketHandle;
    char szConnectIP[30];   // 远端IP
    unsigned short siConnectPort;    // 远端PORT
    char szLocalIp[30];     // 本地IP
    unsigned short siLocalPort;      // 本地PORT
  }CONNECT_INFO;


  typedef struct tagClientDetailInfo
  {
    tagClientDetailInfo() 
    {
      // modified by liusg 20170105 支持不确认长度的大数据接收
      memset(this, 0x00, sizeof(CONNECT_INFO));
      pclTcpConnect = NULL;
      pszRecvBuf = NULL;
      iRecvBufferSize = 0;
      iRcvSum = 0;
      strRecvBuf.clear();
      // modified end
    }
    CONNECT_INFO stConnectInfo;    // 连接信息


    void*  pclTcpConnect;         // 连接对象
    char*  pszRecvBuf;            // 接收缓冲区
    int    iRecvBufferSize;       // 接收缓冲区大小
    int    iRcvSum;               // 总接收数据长度
    std::string strRecvBuf;       // 对应连接大数据接收缓存区 // add by liusg 20170105 支持不确认长度的大数据接收
  }CLIENT_DETAIL_INFO;

}


#pragma once
class CCommuAnalyzer
{
public:
  CCommuAnalyzer(void);
  virtual ~CCommuAnalyzer(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);




protected:
  int m_iNetPackHeadLen;   // 网络包头长度
  int m_iNetPackTailLen;   // 网络包体长度


};


#include "StdAfx.h"
#include "CommuAnalyzer.h"
#include <iostream>
#include <WinSock2.h>




CCommuAnalyzer::CCommuAnalyzer(void)
  :m_iNetPackHeadLen(6)
  ,m_iNetPackTailLen(0)
{
}




CCommuAnalyzer::~CCommuAnalyzer(void)
{
}


bool CCommuAnalyzer::PackNetPackage(char* pszBodyIn, int iBodyLenIn, char*& pszNetBufOut, int& iBufLenOut)
{
  bool bReturn = false;
  int  iHeadLen = 6;
  int  iTailLen = 0;


//   if (pszBodyIn == NULL) {
//     std::cout<< "业务报文入参无效" << std::endl;
//   }
//   else 
  {
    iBufLenOut = iHeadLen + iBodyLenIn + iTailLen;


    pszNetBufOut = new char[iBufLenOut];
    memset(pszNetBufOut, 0x00, iBufLenOut);
    if (pszNetBufOut == NULL) 
    {
      std::cout<< "分配内存存储打包后的网络报文失败" << std::endl;
    }
    else 
    {
      // 报头
      pszNetBufOut[0] = '\n';
      pszNetBufOut[1] = '\r';
      memcpy(pszNetBufOut + 2, &iBodyLenIn, sizeof(int));
      // 报体
      memcpy(pszNetBufOut + iHeadLen, pszBodyIn, iBodyLenIn);
      // 无包尾
    }
    bReturn = true;
  }


  return bReturn;
}


int CCommuAnalyzer::IsExistDirtyData(char* pszNetRcvBufIn, int iNetRcvBufLenIn, int& iSkipLen)
{
  int iReturn = 0;
  iSkipLen = 0;


  if ((iNetRcvBufLenIn - 2 > 0) && (pszNetRcvBufIn[0] != '\n' && pszNetRcvBufIn[1] != '\r') )
  {
    iReturn = -1;
    std::cout<< "有脏数据,返回值:    " << iReturn << ((iReturn == -1) ? ":清理脏数据":":中断网络") << std::endl;


    int iScanPos = 0;
    while(iNetRcvBufLenIn - iScanPos - 2> 0) 
    {
      if (pszNetRcvBufIn[iScanPos] == '\n' && pszNetRcvBufIn[iScanPos+1] == '\r') 
      {
        break;
      }
      iScanPos++;
    }
    iSkipLen = iScanPos;
  }
    
  return iReturn;
}


bool CCommuAnalyzer::IsHasFullPackage(char* pszNetRcvBufIn, int iNetRcvBufLenIn)
{
  bool bReturn = false;
  
  if (iNetRcvBufLenIn >= 6) 
  {
    int iBodyLen = 0;
    memcpy(&iBodyLen, (pszNetRcvBufIn + 2), sizeof(int));
    iBodyLen = ntohl(iBodyLen);
    
    if (iBodyLen <= iNetRcvBufLenIn - 6)
    {
      bReturn = true;
    }
    else 
    {
//      std::cout<< "网络缓存数据不足" << std::endl;
    }
  }
  else 
  {
//    std::cout<< "网络缓存数据不足" << std::endl;
  }
  
  return bReturn;
}


bool CCommuAnalyzer::UnpackNetPackage(char* pszNetRcvBufIn, int iNetRcvBufLenIn, char*& pszBodyOut, int& iBodyLenOut, int& iHeadLenOut, int& iTailLenOut)
{
  bool bReturn = false;


  int iBodyLen = 0;
  memcpy(&iBodyLen, (pszNetRcvBufIn + 2), sizeof(int));
  iBodyLenOut = ntohl(iBodyLen);
  iHeadLenOut = 6;
  iTailLenOut = 0;




  if (iBodyLenOut == 0) 
  {
    pszBodyOut = NULL;
    bReturn = true;
  }
  else 
  {
    pszBodyOut = new char[iBodyLenOut + 1];
    if (pszBodyOut == NULL)
    {
      std::cout<< "分配内存存储解包后的业务报文失败" << std::endl;
    }
    else 
    {
      memset(pszBodyOut, 0x00, iBodyLenOut + 1);
      memcpy(pszBodyOut, pszNetRcvBufIn + iHeadLenOut, iBodyLenOut);
    }
  }


  return bReturn;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值