#include "CommonDefine.h"
class CCommuApplication
{
public:
CCommuApplication(void);
virtual ~CCommuApplication(void);
/*
* Desc:
* 回调返回接收到的完整网络报文
* Pram:
* refConnectInfo 连接参数信息
* pszBussBufOut 完整的网络报文 【输入参数,由分析器(CommuAnalyzer)产生,由应用(CommuApplication)负责删除】
* iBufLenOut 网络报文长度
* Retr:
* void 无返回
*/
virtual void FromNet(TCPCONNECT::CONNECT_INFO& refConnectInfo, char* pszBussBufOut, int iBufLenOut);
/*
* Desc:
* 回调返回网络事件通知
* Pram:
* refConnectInfo 连接参数信息
* enEventType 网络事件类型,参看 TCPCONNECT::EVENT_TYPE 定义
* Retr:
* void 无返回
*/
virtual void NetEvent(TCPCONNECT::CONNECT_INFO& refConnectInfo, int enEventType);
};
#include "StdAfx.h"
#include <iostream>
#include "CommuApplication.h"
CCommuApplication::CCommuApplication(void)
{
}
CCommuApplication::~CCommuApplication(void)
{
}
void CCommuApplication::FromNet(TCPCONNECT::CONNECT_INFO& refConnectInfo, char* pszBussBufOut, int iBufLenOut)
{
struct TEST_STRUCT
{
int i;
int b;
double c;
char sz2[30];
double d;
};
TEST_STRUCT stStruct;
memcpy(&stStruct, pszBussBufOut, sizeof(stStruct));
std::cout<< "接收到来自服务端数据包:" << stStruct.sz2 << " i = " << stStruct.i << std::endl;
static int iCount = 0;
static int iBefore = 0;
iCount++;
if (iCount ==1)
{
iBefore = GetTickCount();
}
else if (iCount == 200000)
{
int iLastTime = GetTickCount()- iBefore;
//std::cout << "接收20万数据,共费时:" << iLastTime << "毫秒" << std::endl;
}
else if (iCount ==17)//???
{
int i = 0;
}
delete[] pszBussBufOut;
pszBussBufOut = NULL;
}
void CCommuApplication::NetEvent(TCPCONNECT::CONNECT_INFO& refConnectInfo, int enEventType)
{
//为什么不用switch,case结构
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::CONNECT_SUCCESS_EVENT)
{
//std::cout << " = 0, // 连接成功" << std::endl;
char szBuf[100] = {0};
strncpy_s(szBuf, "12345567890", 10);
send(refConnectInfo.iSocketHandle, szBuf, 10, 0);
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::CONNECT_FAILD_EVENT)
{
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 1, // 连接失败" << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::LISTEN_SUCCESS_EVENT)
{
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 5, // 侦听成功" << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::LISTEN_FAILD_EVENT)
{
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 6, // 侦听失败" << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::CONNECT_GET_IN_EVENT)
{
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 7, // 连接接入" << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::CONNECT_QUIT_EVENT)
{
SOCKADDR_IN localAddrIn;
int iLocalAddrInLen = sizeof(localAddrIn);
getsockname(refConnectInfo.iSocketHandle, (sockaddr*)&localAddrIn, &iLocalAddrInLen);
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 8, // 连接退出 客户端Port:" << ntohs(localAddrIn.sin_port) << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::CONNECT_BREAKED_EVENT)
{
SOCKADDR_IN localAddrIn;
int iLocalAddrInLen = sizeof(localAddrIn);
getsockname(refConnectInfo.iSocketHandle, (sockaddr*)&localAddrIn, &iLocalAddrInLen);
if (ntohs(localAddrIn.sin_port) == 52428)
{
int itst = 0;
}
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 12 // 断开连接 客户端Port:" << ntohs(localAddrIn.sin_port) << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::HAS_DIRTY_DATA_CLEAR)
{
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 50 // 连接上存在脏数据,即时清除:" << ntohs(localAddrIn.sin_port) << std::endl;
}
if (enEventType == (int)TCPCONNECT::EVENT_TYPE::HAS_DIRTY_DATA_BREAK)
{
//std::cout << "SOCKET句柄:" << refConnectInfo.iSocketHandle << " = 51 // 连接上存在脏数据,断开网络:" << ntohs(localAddrIn.sin_port) << std::endl;
}
}
\
#pragma once
#include <map>
#include <list>
#include <string>
#include <Windows.h>
#include "CommuApplication.h"
#include "CommuAnalyzer.h"
#include "TCPConnect.h"
class CNetCommunication
{
public:
CNetCommunication(void);
~CNetCommunication(void);
public:
/*
* Desc:
* 设置网络通讯模块参数
* Pram:
* enCommMode 决定网络模块是以服务端还是客户端模式运行
* enBlockMode 决定网络模块是否以阻塞或非阻塞模式运行
* strIP 服务端模式下表示侦听的IP及端口
* 客户端模式下表示远程服务的IP及端口
* iCommuTimeout 通讯超时时间(以秒为单位),仅在客户端模式下生效
* 服务端模式下由客户端设置通讯超时告知,并通过SetCommuTimeout()进行设置
* Retr:
* void 无返回
*/
void SetNetCommParam(TCPCONNECT::COMMUNICATION_MODE& refenCommMode, TCPCONNECT::BLOCKING_MODE& refenBlockMode, std::string& refstrIP, unsigned short& refsiPort, int iCommuTimeout = 0);
/*
* Desc:
* 注册通讯分析器
* 默认的通讯分析器只含简单的网络层组包解包逻辑逻辑,不包含对于业务协议的包。网络包规则如下:
* 网络包头包括:包头识别码(换行回车符:'\n\r')+ 一个整型值的长度,无包尾
* 注:当符合以下条件的情况下可以不调用该接口
* 1、业务报文件长度小于 TCPConnect中定义的:最大网络接收缓冲区大小
* 2、对网络包组包规则无特殊要求
* Pram:
* pclCommuAnalyzer 该分析器必须实现网络包的组包与解包
* Retr:
* void 无返回
*/
void RigisterPacker(CCommuAnalyzer* pclCommuAnalyzer);
/*
* Desc:
* 注册应用对象
* Pram:
* pclCommuAnalyzer 必须实现接收、已经发送通知接口
*
* Retr:
* void 无返回
*/
void RigisterApp(CCommuApplication* pclCommuApplication);
/*
* Desc:
* 启动通讯模块
* Pram:
* bReconnect 决定是否进行自动重连【仅在客户端模式下生效,服务端模式下采用默认值】
* iTimeout 超时时间(以秒为单位)【在客户端模式表示连接超时,服务端模式下表示侦听超时】
* Retr:
* bool 启动成功为 true, 启动失败为 false
*/
bool Start(bool bReconnect = false, int iTimeout = 0);
/*
* Desc:
* 停止通讯模块
* Pram:
* bEnforce 决定是否强制停止 默认非强制停止
*
* Retr:
* bool 停止成功为 true, 停止失败为 false
*/
bool Stop(bool bEnforce = false);
/*
* Desc:
* 停止某个连接【仅服务端模型下有效】
* Pram:
*
* Retr:
* bool 停止成功为 true, 停止失败为 false
*/
bool Stop(TCPCONNECT::CONNECT_INFO& stConnectInfo);
/*
* Desc:
* 发送数据
* Pram:
* refConnectInfo 连接信息
* pszData 待发送数据
* iDataLen 待发送数据的长度
* Retr:
* bool 发送成功为 true, 发送失败为 false
*/
bool SendData(TCPCONNECT::CONNECT_INFO& refConnectInfo, char* pszData, int iDataLen);
private:
/*
* Desc:
* 设置通讯超时,该函数只能由 通讯应用来调用 CCommuApplication
* Pram:
* iCommuTimeout 连接信息
* Retr:
* void 无返回
*/
void SetCommuTimeout(int iCommuTimeout){ m_iCommuTimeout = iCommuTimeout; }
private:
mylib::CMyCriticalSection m_csCommunication;
TCPCONNECT::COMMUNICATION_MODE m_enCommMode;
TCPCONNECT::BLOCKING_MODE m_enBlockMode;
std::string m_strIP;
unsigned short m_siPort;
int m_iCommuTimeout; // 通讯超时 控制心跳
bool m_bReconnect;
int m_iTimeout; // 超时【客户端模式表示连接超时,服务端模式下表示侦听超时】
CCommuAnalyzer* m_pclCommuAnalyzer;
CCommuApplication* m_pclCommuApplication;
CTCPConnect* m_clTcpConnect;
};
#include "StdAfx.h"
#include <assert.h>
#include "NetCommunication.h"
#include "TCPServer.h"
#include "TCPClient.h"
#include <iostream>
CNetCommunication::CNetCommunication(void)
:m_enCommMode(TCPCONNECT::MODE_CLIENT)
,m_enBlockMode(TCPCONNECT::MODE_BLOCKING)
,m_strIP("")
,m_siPort(0)
,m_iCommuTimeout(3)
,m_iTimeout(10)
,m_pclCommuAnalyzer(NULL)
,m_pclCommuApplication(NULL)
,m_clTcpConnect(NULL)
{
}
CNetCommunication::~CNetCommunication(void)
{
}
void CNetCommunication::SetNetCommParam(TCPCONNECT::COMMUNICATION_MODE& refenCommMode, TCPCONNECT::BLOCKING_MODE& refenBlockMode, std::string& refstrIP, unsigned short& refsiPort, int iCommuTimeout)
{
m_enCommMode = refenCommMode;
m_enBlockMode = refenBlockMode;
m_strIP = refstrIP;
m_siPort = refsiPort;
m_iCommuTimeout = iCommuTimeout;
}
void CNetCommunication::RigisterPacker(CCommuAnalyzer* pclCommuAnalyzer)
{
assert(pclCommuAnalyzer != NULL);
m_pclCommuAnalyzer = pclCommuAnalyzer;
}
void CNetCommunication::RigisterApp(CCommuApplication* pclCommuApplication)
{
assert(pclCommuApplication != NULL);
m_pclCommuApplication = pclCommuApplication;
}
bool CNetCommunication::Start( bool bReconnect, int iTimeout )
{
bool bReturn = false;
mylib::CCriticalSectionGuard myGuard(m_csCommunication);
if ( m_clTcpConnect != NULL )
{
bReturn = true;//已连接
}
else
{
m_iTimeout = max(3, iTimeout); // 最低3秒的延时
if ( m_enCommMode == TCPCONNECT::MODE_CLIENT )
{
m_clTcpConnect = new CTCPClient();
}
else
{
m_clTcpConnect = new CTCPServer();
}
if ( m_clTcpConnect != NULL )
{
if ( m_pclCommuAnalyzer == NULL || m_pclCommuApplication == NULL )
{
std::cout << "未注册通讯分析器或通讯应用" << std::endl;
}
else
{
m_clTcpConnect->RigisterPacker(m_pclCommuAnalyzer);
m_clTcpConnect->RigisterApp(m_pclCommuApplication);
//启动连接
bReturn = m_clTcpConnect->Start(m_strIP, m_siPort, m_enBlockMode, bReconnect, m_iTimeout);
if ( !bReturn )
{
std::cout << ((m_enCommMode == TCPCONNECT::MODE_CLIENT) ? "客户端":"服务端") << "启动失败" << std::endl;
}
else
{
std::cout << ((m_enCommMode == TCPCONNECT::MODE_CLIENT) ? "客户端":"服务端") << "启动成功" << std::endl;
bReturn = true;
}
}
if ( !bReturn )
{
delete m_clTcpConnect;
m_clTcpConnect = NULL;
}
}
}
return bReturn;
}
bool CNetCommunication::Stop(bool bEnforce)
{
bool bReturn = false;
mylib::CCriticalSectionGuard myGuard(m_csCommunication);
if (m_clTcpConnect == NULL)
{
bReturn = true;
}
else
{
bReturn = m_clTcpConnect->Stop(bEnforce);
if (bReturn == true)
{
delete m_clTcpConnect;
m_clTcpConnect = NULL;
}
}
return bReturn;
}
bool CNetCommunication::Stop(TCPCONNECT::CONNECT_INFO& stConnectInfo)
{
bool bReturn = false;
mylib::CCriticalSectionGuard myGuard(m_csCommunication);
if (m_clTcpConnect == NULL)
{
bReturn = true;
}
else
{
if (m_enCommMode == TCPCONNECT::MODE_SERVER)
{
bReturn = ((CTCPServer*)m_clTcpConnect)->StopConnected(stConnectInfo);
}
}
return bReturn;
}
bool CNetCommunication::SendData(TCPCONNECT::CONNECT_INFO& refConnectInfo, char* pszData, int iDataLen)
{
bool bReturn = false;
//mylib::CCriticalSectionGuard myGuard(m_csCommunication); //可能死锁
bReturn = m_clTcpConnect->SendData(refConnectInfo, pszData, iDataLen);
return bReturn;
}