| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- #include "StdAfx.h"
- #include "NetClient.h"
- #include "NetLinkMain.h"
- #include "PduEntity.h"
- #include "PduEntityHead.h"
- CNetClient::CNetClient(CNetLinkMain* pParent, PDU_LINK_TYPE a_nLinkType, bool IsAutoReconnect) : CSocketBase(pParent), m_Assistant(IsAutoReconnect)
- {
- m_Assistant.m_pParent = this;
- m_Assistant.linkType() = a_nLinkType;
- ZeroMemory(&m_Overlapped, sizeof(m_Overlapped));
- m_WsaBuf.buf = NULL;
- m_WsaBuf.len = 0;
- __resetBuffer();
- }
- CNetClient::~CNetClient(void)
- {
- TRACE(_T("@CNetClient::~CNetClient\r\n"));
- }
- /*****************************************************************
- **【函数名称】 __resetBuffer
- **【函数功能】 重置接收缓冲
- **【参数】
- **【返回值】
- ****************************************************************/
- void CNetClient::__resetBuffer( void )
- {
- ZeroMemory(m_szBuffer, PDU_BUFFER_LEN);
- m_HasRead = 0;
- }
- /*****************************************************************
- **【函数名称】 __create
- **【函数功能】 创建
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::__create( void )
- {
- ASSERT(m_Socket == INVALID_SOCKET);
- m_Socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
- if(m_Socket == INVALID_SOCKET)
- return false;
- else
- return true;
- }
- /*****************************************************************
- **【函数名称】 __connect
- **【函数功能】 连接服务器
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::__connect( LPCTSTR FarAddr, int FarPort )
- {
- SOCKADDR_IN sockAddr;
- memset(&sockAddr,0,sizeof(sockAddr));
- sockAddr.sin_family = AF_INET;
- sockAddr.sin_addr.s_addr = inet_addr(FarAddr);
- if (sockAddr.sin_addr.s_addr == INADDR_NONE)
- {
- LPHOSTENT lphost;
- lphost = gethostbyname(FarAddr);
- if (lphost != NULL)
- sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
- else
- return false;
- }
- sockAddr.sin_port = htons((u_short)FarPort);
- if(connect(m_Socket, (sockaddr*)&sockAddr, sizeof(sockAddr)) == 0)
- {
- m_pParent->onConnEstablished(this);
- return true;
- }
- else
- {
- m_pParent->onConnFailed(this);
- return false;
- }
- }
- /*****************************************************************
- **【函数名称】 __send
- **【函数功能】 发送数据
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::__send( UCHAR a_szBuf[], UINT a_BufLen )
- {
- UINT nHasSend = 0;
- while(nHasSend < a_BufLen)
- {
- int nSend = send(m_Socket, (LPCTSTR)&a_szBuf[nHasSend], a_BufLen - nHasSend, 0);
- if(nSend > 0)
- {
- nHasSend += nSend;
- }
- else
- {
- if(WSAGetLastError() == WSAEWOULDBLOCK) // 阻塞
- Sleep(10);
- else
- return false;
- }
- } // end while
- return true;
- }
- /*****************************************************************
- **【函数名称】 doJob
- **【函数功能】 开始解析接收的数据并投递接收请求
- **【参数】
- **【返回值】
- ****************************************************************/
- void CNetClient::doJob( OVERLAPPED* pOverLapped, DWORD BytesTransfered )
- {
- TRACE(_T("recv: %d @CNetClient::doJob\r\n"), BytesTransfered);
- if(m_DropFlag)
- return;
- if(BytesTransfered == 0)
- {
- onDisconnect();
- return;
- }
- // 对接收的数据进行处理
- m_HasRead += BytesTransfered;
- // 如果已经接收到完整的包头
- while(m_HasRead > PDU_HEAD_LEN) // 有可能一次接收到多个完整命令
- {
- CPduEntityHead pduHead;
- // 解析PDU数据包头
- if(!pduHead.Decode((UCHAR*)m_szBuffer))
- {
- __resetBuffer(); // 如果解析失败,清除缓冲区
- break;
- } // end if
- // 如果数据包完整(HEAD + DATA)
- if(m_HasRead >= (PDU_HEAD_LEN + pduHead.GetDataLen()))
- {
- // 拷贝当前要处理的数据到临时缓冲区
- UCHAR szTmpBuf[PDU_MAX_DATA_LEN] = { 0 };
- memcpy_s(szTmpBuf, PDU_MAX_DATA_LEN, m_szBuffer, PDU_HEAD_LEN + pduHead.GetDataLen());
- // 清除已处理的数据(数据前移)
- m_HasRead = m_HasRead - (PDU_HEAD_LEN + pduHead.GetDataLen());
- memmove_s(m_szBuffer, PDU_BUFFER_LEN, &m_szBuffer[PDU_HEAD_LEN + pduHead.GetDataLen()], m_HasRead);
- ZeroMemory(&m_szBuffer[m_HasRead], PDU_BUFFER_LEN - m_HasRead);
- // 对数据进行处理
- CPduEntity pduEntity(&pduHead, &szTmpBuf[PDU_HEAD_LEN]);
- pduEntity.SetAssoSocket(m_Socket);
- m_pParent->onRecvCommand(&pduEntity);
- }
- else
- {
- break; // 如果当前数据不是一个完整数据包,退出循环
- } // end if
- } // end while
- ready4Recv();
- }
- /*****************************************************************
- **【函数名称】 isAlive
- **【函数功能】 客户端是否断链
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::isAlive( void )
- {
- return monitor();
- }
- /*****************************************************************
- **【函数名称】 __onDisconnect
- **【函数功能】 网络断连的处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CNetClient::onDisconnect( void )
- {
- TRACE(_T("@CNetClient::onDisconnect\r\n"));
- if(m_DropFlag)
- return;
- _close();
- __create();
- __resetBuffer();
- m_pParent->onConnFailed(this);
- }
- /*****************************************************************
- **【函数名称】 connect2Server
- **【函数功能】 连接到SERVER端
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::connect2Server( const CString& a_FarIp, int a_FarPort, PDU_DEV_TYPE a_FarType, int a_FarId )
- {
- if(!__create())
- return false;
- m_Assistant.setFarLinkInfo(a_FarIp, a_FarPort);
- m_Assistant.setFarDevInfo(a_FarType, a_FarId);
- if(__connect(a_FarIp, a_FarPort))
- return true;
- else
- return false;
- }
- /*****************************************************************
- **【函数名称】 regist
- **【函数功能】 向服务器注册
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::regist( void )
- {
- // 生成注册命令
- CPduEntity reg(PDU_CMD_REG);
- PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN;
- int DevId = -1;
- m_Assistant.getFarDevInfo(DevType, DevId);
- reg.SetPeerDevInfo(DevType, DevId); // 填充接收方信息
- m_pParent->getLocalInfo(DevType, DevId);
- reg.SetLocalDevInfo(DevType, DevId); // 填充发送方信息
- // 发送注册命令
- return sendDirectly(®);
- }
- /*****************************************************************
- **【函数名称】 monitor
- **【函数功能】 发送心跳监听
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::monitor( void )
- {
- CPduEntity Monitor(PDU_CMD_LISTEN);
- PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN;
- int DevId = -1;
- m_Assistant.getFarDevInfo(DevType, DevId);
- Monitor.SetPeerDevInfo(DevType, DevId); // 填充接收方信息
- m_pParent->getLocalInfo(DevType, DevId);
- Monitor.SetLocalDevInfo(DevType, DevId); // 填充发送方信息
- // 发送心跳监听
- return sendDirectly(&Monitor);
- }
- /*****************************************************************
- **【函数名称】 sendDirectly
- **【函数功能】 直接发送PDU命令
- **【参数】 a_pCmd 要发送的命令实体
- **【返回值】
- ****************************************************************/
- bool CNetClient::sendDirectly( CPduEntity* a_pCmd )
- {
- ASSERT(m_Socket != INVALID_SOCKET);
- // 生成要发送的数据缓冲区
- 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 __send(szBuf, nLen);
- }
- /*****************************************************************
- **【函数名称】 sendPdu
- **【函数功能】 发送PDU命令
- **【参数】 a_pCmd 要发送的命令实体
- **【返回值】
- ****************************************************************/
- bool CNetClient::sendPdu( CPduEntity* a_pCmd )
- {
- PDU_DEV_TYPE DevType;
- int DevId;
- m_Assistant.getFarDevInfo(DevType, DevId);
- a_pCmd->SetPeerDevInfo(DevType, DevId);
- return sendDirectly(a_pCmd);
- }
- /*****************************************************************
- **【函数名称】 ready4Recv
- **【函数功能】 准备接收数据
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CNetClient::ready4Recv( void )
- {
- // 初始化变量
- DWORD dwFlags = MSG_PARTIAL;
- DWORD dwBytes = 0;
- m_WsaBuf.buf = &m_szBuffer[m_HasRead];
- m_WsaBuf.len = PDU_BUFFER_LEN - m_HasRead;
- ZeroMemory(&m_Overlapped, sizeof(OVERLAPPED));
- // 投递WSARecv请求
- int nBytesRecv = WSARecv(m_Socket, &m_WsaBuf, 1, &dwBytes, &dwFlags, &m_Overlapped, NULL );
- if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
- {
- TRACE(_T("WSARecv error@ CNetClient::ready4Recv\r\n"));
- onDisconnect();
- return false;
- }
- return true;
- }
- /*****************************************************************
- **【函数名称】 drop
- **【函数功能】 丢弃此客户端
- **【参数】
- **【返回值】
- ****************************************************************/
- void CNetClient::drop( void )
- {
- m_DropFlag = true;
- _close();
- }
- /*****************************************************************
- **【函数名称】 getLocalInfo
- **【函数功能】 获取本端设备类型及ID
- **【参数】
- **【返回值】
- ****************************************************************/
- void CNetClient::getLocalInfo( PDU_DEV_TYPE& a_DevType, int& a_DevId ) const
- {
- m_pParent->getLocalInfo(a_DevType, a_DevId);
- }
|