// ..\..\..\Public\PduLink\PduSocket.cpp : 实现文件 // #include "StdAfx.h" #include "PduSocket.h" #include "PduSocketMonitor.h" #include "PduMain.h" #include "PduEntity.h" #include "PduEntityHead.h" // CPduSocket CPduSocket::CPduSocket(CPduMain* a_pParent, PDU_LINK_TYPE a_nLinkType, bool IsAutoReconnect) { // 初始化监控信息 m_pSocketMonitor = new CPduSocketMonitor(IsAutoReconnect); m_pSocketMonitor->SetLinkType(a_nLinkType); // 连接方式 m_pParent = a_pParent; // 清空SOCKET数据缓冲区 __InitData(); } CPduSocket::~CPduSocket() { if(m_pSocketMonitor != NULL) delete m_pSocketMonitor; } /***************************************************************** **【函数名称】 __InitData **【函数功能】 清空SOCKET数据缓冲区 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::__InitData() { m_nHasRead = 0; // 已读取的数据缓冲区长度 memset(m_szPdu, 0, PDU_HEAD_LEN + PDU_MAX_DATA_LEN); // 已读取的缓冲区内容 } /***************************************************************** **【函数名称】 GetPeerLinkInfo **【函数功能】 读取SOCKET连接信息 **【参数】 **【返回值】 a_strIp SOCKET对端IP a_nPort SOCKET对端PORT ****************************************************************/ void CPduSocket::GetPeerLinkInfo(CString& a_strIp, int& a_nPort) { m_pSocketMonitor->GetPeerLinkInfo(a_strIp, a_nPort); } /***************************************************************** **【函数名称】 GetLinkType **【函数功能】 得到连接类型 **【参数】 **【返回值】 ****************************************************************/ PDU_LINK_TYPE CPduSocket::GetLinkType() { return m_pSocketMonitor->GetLinkType(); } /***************************************************************** **【函数名称】 GetPeerDevInfo **【函数功能】 读取对端设备信息 **【参数】 **【返回值】 a_nDevType 对端设备类型 a_nDevId 对端设备ID ****************************************************************/ void CPduSocket::GetPeerDevInfo(PDU_DEV_TYPE& a_nDevType, int& a_nDevId) { m_pSocketMonitor->GetPeerDevInfo(a_nDevType, a_nDevId); } /***************************************************************** **【函数名称】 SetPeerDevInfo **【函数功能】 设置对端设备信息 **【参数】 a_nDevType 对端设备类型 a_nDevId 对端设备ID **【返回值】 ****************************************************************/ void CPduSocket::SetPeerDevInfo(PDU_DEV_TYPE a_nDevType, int a_nDevId) { m_pSocketMonitor->SetPeerDevInfo(a_nDevType, a_nDevId); } /***************************************************************** **【函数名称】 GetLocalInfo **【函数功能】 设置本端设备信息 **【参数】 a_nDevType 本端设备类型 a_nDevId 本端设备ID **【返回值】 ****************************************************************/ void CPduSocket::GetLocalInfo(PDU_DEV_TYPE& a_nDevType, int& a_nDevId) { m_pParent->GetLocalInfo(a_nDevType,a_nDevId); } /***************************************************************** **【函数名称】 ConnectToServer **【函数功能】 连接到SERVER端 **【参数】 **【返回值】 ****************************************************************/ BOOL CPduSocket::ConnectToServer(const CString& a_strFarIp, int a_nFarPort, PDU_DEV_TYPE a_nFarType, int a_nFarId) { if(!Create()) return FALSE; // 设置监控信息 m_pSocketMonitor->SetPeerLinkInfo(a_strFarIp, a_nFarPort); m_pSocketMonitor->SetPeerDevInfo(a_nFarType, a_nFarId); // 开始连接 if(Connect(a_strFarIp, a_nFarPort) == 0) { return TRUE; } return FALSE; } /***************************************************************** **【函数名称】 Regist **【函数功能】 注册SOCKET连接 **【参数】 **【返回值】 ****************************************************************/ BOOL CPduSocket::Regist( void ) { // 生成注册命令 CPduEntity reg(PDU_CMD_REG); PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN; int DevId = -1; m_pSocketMonitor->GetPeerDevInfo(DevType, DevId); reg.SetPeerDevInfo(DevType, DevId); // 填充接收方信息 m_pParent->GetLocalInfo(DevType, DevId); reg.SetLocalDevInfo(DevType, DevId); // 填充发送方信息 // 发送注册命令 return SendDirectly(®); } /***************************************************************** **【函数名称】 Monitor **【函数功能】 发送心跳监听 **【参数】 **【返回值】 ****************************************************************/ BOOL CPduSocket::Monitor( void ) { CPduEntity Monitor(PDU_CMD_LISTEN); PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN; int DevId = -1; m_pSocketMonitor->GetPeerDevInfo(DevType, DevId); Monitor.SetPeerDevInfo(DevType, DevId); // 填充接收方信息 m_pParent->GetLocalInfo(DevType, DevId); Monitor.SetLocalDevInfo(DevType, DevId); // 填充发送方信息 // 发送心跳监听 return SendDirectly(&Monitor); } /***************************************************************** **【函数名称】 SendDirectly **【函数功能】 发送PDU命令 **【参数】 a_pCmd 要发送的命令实体 **【返回值】 ****************************************************************/ BOOL CPduSocket::SendDirectly(CPduEntity* a_pCmd) { // 生成要发送的数据缓冲区 UCHAR szBuf[PDU_HEAD_LEN + PDU_MAX_DATA_LEN]; ZeroMemory(szBuf, PDU_HEAD_LEN + PDU_MAX_DATA_LEN); int nLen = a_pCmd->CreatePackge(szBuf); // 发送 return __SendBuf(szBuf, nLen); } /***************************************************************** **【函数名称】 SendPdu **【函数功能】 发送PDU命令 **【参数】 a_pCmd 要发送的命令实体 **【返回值】 ****************************************************************/ BOOL CPduSocket::SendPdu( CPduEntity* a_pCmd ) { PDU_DEV_TYPE DevType; int DevId; m_pSocketMonitor->GetPeerDevInfo(DevType, DevId); a_pCmd->SetPeerDevInfo(DevType, DevId); return SendDirectly(a_pCmd); } /***************************************************************** **【函数名称】 OnConnect **【函数功能】 连接状态事件 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnConnect(int nErrorCode) { if(nErrorCode == 0) // 连接建立 { m_pParent->OnConnEstablished(this); } else // 连接失败 { __InitData(); // 清空SOCKET数据缓冲区 m_pParent->OnConnFailed(this); } // end if CAsyncSocket::OnConnect(nErrorCode); } /***************************************************************** **【函数名称】 OnClose **【函数功能】 关闭事件 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnClose(int nErrorCode) { // 必要操作 Close(); Create(); // 清空SOCKET数据缓冲区 __InitData(); m_pParent->OnConnFailed(this); // 连接断开 CAsyncSocket::OnClose(nErrorCode); } /***************************************************************** **【函数名称】 OnReceive **【函数功能】 消息接收事件 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnReceive(int nErrorCode) { // 读数据 int nRead = Receive(&m_szPdu[m_nHasRead], PDU_HEAD_LEN + PDU_MAX_DATA_LEN - m_nHasRead); if(nRead == SOCKET_ERROR) return; // 对接收的数据进行处理 m_nHasRead += nRead; // 如果已经接收到完整的包头 while(m_nHasRead > PDU_HEAD_LEN) // 有可能一次接收到多个完整命令 { CPduEntityHead pduHead; // 解析PDU数据包头 if(!pduHead.Decode(m_szPdu)) { __InitData(); // 如果解析失败,清除缓冲区 break; } // end if // 如果数据包完整(HEAD + DATA) if(m_nHasRead >= (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_szPdu, PDU_HEAD_LEN + pduHead.GetDataLen()); // 清除已处理的数据(数据前移) m_nHasRead = m_nHasRead - (PDU_HEAD_LEN + pduHead.GetDataLen()); memcpy(m_szPdu, &m_szPdu[PDU_HEAD_LEN + pduHead.GetDataLen()], m_nHasRead); memset(&m_szPdu[m_nHasRead], 0, (PDU_HEAD_LEN + PDU_MAX_DATA_LEN - m_nHasRead)); // 对数据进行处理 CPduEntity pduEntity(&pduHead, &szTmpBuf[PDU_HEAD_LEN]); pduEntity.SetAssoSocket(m_hSocket); m_pParent->OnRecvCommand(&pduEntity); } else { break; // 如果当前数据不是一个完整数据包,退出循环 } // end if } // end while CAsyncSocket::OnReceive(nErrorCode); } /***************************************************************** **【函数名称】 OnSend **【函数功能】 消息发送事件 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnSend(int nErrorCode) { // TODO: 在此添加专用代码和/或调用基类 CAsyncSocket::OnSend(nErrorCode); } /***************************************************************** **【函数名称】 __SendBuf **【函数功能】 发送数据缓冲区 **【参数】 a_szBuf[] 内容 a_nBufLen 长度 **【返回值】 ****************************************************************/ BOOL CPduSocket::__SendBuf(UCHAR a_szBuf[], UINT a_nBufLen) { UINT nHasSend = 0; while(nHasSend < a_nBufLen) { int nSend = Send(&a_szBuf[nHasSend], a_nBufLen - nHasSend); if(nSend > 0) { nHasSend += nSend; } else { if(GetLastError() == WSAEWOULDBLOCK) // 阻塞 Sleep(10); else return FALSE; } } return TRUE; } /***************************************************************** **【函数名称】 OnConnEstablisthed **【函数功能】 SOCKET连接建立事件处理 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnConnEstablished() { return m_pSocketMonitor->OnConnEstablisthed(this); } /***************************************************************** **【函数名称】 OnConnFailed **【函数功能】 SOCKET连接断开/失败事件处理 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnConnFailed() { return m_pSocketMonitor->OnConnFailed(this); } /***************************************************************** **【函数名称】 OnConnRegistOK **【函数功能】 SOCKET连接注册成功事件处理 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnConnRegistOK() { return m_pSocketMonitor->OnConnRegistOK(this); } /***************************************************************** **【函数名称】 OnConnRegistFailed **【函数功能】 SOCKET连接注册失败事件处理 **【参数】 **【返回值】 ****************************************************************/ void CPduSocket::OnConnRegistFailed() { return m_pSocketMonitor->OnConnRegistFailed(this); }