#include "stdafx.h" #include "NetLinkClient.h" #include "PduEntity.h" #include "PduEntityHead.h" #include "NetLinkMgr.h" CNetLinkClient::CNetLinkClient(CNetLinkMgr* a_pParent) : m_IsMainClient(false), m_pParent(a_pParent),m_FarEndIp(_T("")), m_FarEndPort(0) { // 清空SOCKET数据缓冲区 __initBuffer(); } CNetLinkClient::~CNetLinkClient( void ) { Close(); } // CNetLinkClient 成员函数 /***************************************************************** **【函数名称】 __initBuffer **【函数功能】 清空SOCKET数据缓冲区 **【参数】 **【返回值】 ****************************************************************/ void CNetLinkClient::__initBuffer( void ) { m_HasRead = 0; // 已读取的数据缓冲区长度 memset(m_ReadBuffer, 0, PDU_HEAD_LEN + PDU_MAX_DATA_LEN); // 已读取的缓冲区内容 } /***************************************************************** **【函数名称】 __sendBuffer **【函数功能】 发送数据缓冲区 **【参数】 a_Buf[]: 内容 a_BufLen: 长度 **【返回值】 ****************************************************************/ bool CNetLinkClient::__sendBuffer( UCHAR a_Buf[], UINT a_BufLen ) { UINT HasSend = 0; while(HasSend < a_BufLen) { int len = Send(&a_Buf[HasSend], a_BufLen - HasSend); switch(len) { case 0: // 连接已断开 return false; case SOCKET_ERROR: // 发送失败 if(GetLastError() != WSAEWOULDBLOCK) { return false; } Sleep(10); // 阻塞 break; default: HasSend += len; break; } // end switch } // end while return true; } /***************************************************************** **【函数名称】 OnReceive **【函数功能】 消息接收事件 **【参数】 **【返回值】 ****************************************************************/ void CNetLinkClient::OnReceive( int ErrorCode ) { // 读数据 int nRead = Receive(&m_ReadBuffer[m_HasRead], PDU_HEAD_LEN + PDU_MAX_DATA_LEN - m_HasRead); if(nRead == SOCKET_ERROR) return; // 对接收的数据进行处理 m_HasRead += nRead; // 如果已经接收到完整的包头 while(m_HasRead > PDU_HEAD_LEN) // 有可能一次接收到多个完整命令 { CPduEntityHead pduHead; // 解析PDU数据包头 if(!pduHead.Decode(m_ReadBuffer)) { __initBuffer(); // 如果解析失败,清除缓冲区 break; } // end if // 如果数据包完整(HEAD + DATA) if(m_HasRead >= (PDU_HEAD_LEN + pduHead.GetDataLen())) { // 拷贝当前要处理的数据到临时缓冲区 UCHAR szTmpBuf[PDU_MAX_DATA_LEN]; ZeroMemory(szTmpBuf, PDU_MAX_DATA_LEN); memcpy_s(szTmpBuf, PDU_MAX_DATA_LEN, m_ReadBuffer, PDU_HEAD_LEN + pduHead.GetDataLen()); // 清除已处理的数据(数据前移) m_HasRead = m_HasRead - (PDU_HEAD_LEN + pduHead.GetDataLen()); memcpy(m_ReadBuffer, &m_ReadBuffer[PDU_HEAD_LEN + pduHead.GetDataLen()], m_HasRead); memset(&m_ReadBuffer[m_HasRead], 0, (PDU_HEAD_LEN + PDU_MAX_DATA_LEN - m_HasRead)); // 对数据进行处理 CPduEntity pduEntity(&pduHead, &szTmpBuf[PDU_HEAD_LEN]); pduEntity.assoClient() = this; ASSERT(m_pParent != NULL); m_pParent->onCmdRequest(this, &pduEntity); } else { break; // 如果当前数据不是一个完整数据包,退出循环 } // end if } // end while CAsyncSocket::OnReceive(ErrorCode); } /***************************************************************** **【函数名称】 OnConnect **【函数功能】 消息连接事件 **【参数】 **【返回值】 ****************************************************************/ void CNetLinkClient::OnConnect( int ErrorCode ) { GetPeerName(m_FarEndIp, m_FarEndPort); } /***************************************************************** **【函数名称】 OnClose **【函数功能】 关闭事件 **【参数】 **【返回值】 ****************************************************************/ void CNetLinkClient::OnClose( int ErrorCode ) { // 必要操作 Close(); ASSERT(m_pParent != NULL); m_pParent->onClientDisconnect(this); // 连接断开 CAsyncSocket::OnClose(ErrorCode); } /***************************************************************** **【函数名称】 send **【函数功能】 发送PDU命令 **【参数】 a_Pdu: 要发送的命令 **【返回值】 ****************************************************************/ bool CNetLinkClient::send( CPduEntity& a_Pdu ) { a_Pdu.SetPeerDevInfo(m_PeerType, m_PeerId); // 填充接收方信息 // 生成要发送的数据缓冲区 UCHAR Buf[PDU_HEAD_LEN + PDU_MAX_DATA_LEN]; ZeroMemory(Buf, PDU_HEAD_LEN + PDU_MAX_DATA_LEN); int nLen = a_Pdu.CreatePackge(Buf); // 发送 return __sendBuffer(Buf, nLen); } /***************************************************************** **【函数名称】 setPeerInfo **【函数功能】 设置对端类型信息 **【参数】 **【返回值】 ****************************************************************/ void CNetLinkClient::setPeerInfo( PDU_DEV_TYPE a_DevType, int a_DevId ) { m_PeerType = a_DevType; m_PeerId = a_DevId; }