升龙物业 老版本 ocx IPO, 加密狗 转值班电话

NetClient.cpp 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #include "StdAfx.h"
  2. #include "NetClient.h"
  3. #include "NetLinkMain.h"
  4. #include "PduEntity.h"
  5. #include "PduEntityHead.h"
  6. CNetClient::CNetClient(CNetLinkMain* pParent, PDU_LINK_TYPE a_nLinkType, bool IsAutoReconnect) : CSocketBase(pParent), m_Assistant(IsAutoReconnect)
  7. {
  8. m_Assistant.m_pParent = this;
  9. m_Assistant.linkType() = a_nLinkType;
  10. ZeroMemory(&m_Overlapped, sizeof(m_Overlapped));
  11. m_WsaBuf.buf = NULL;
  12. m_WsaBuf.len = 0;
  13. __resetBuffer();
  14. }
  15. CNetClient::~CNetClient(void)
  16. {
  17. TRACE(_T("@CNetClient::~CNetClient\r\n"));
  18. }
  19. /*****************************************************************
  20. **【函数名称】 __resetBuffer
  21. **【函数功能】 重置接收缓冲
  22. **【参数】
  23. **【返回值】
  24. ****************************************************************/
  25. void CNetClient::__resetBuffer( void )
  26. {
  27. ZeroMemory(m_szBuffer, PDU_BUFFER_LEN);
  28. m_HasRead = 0;
  29. }
  30. /*****************************************************************
  31. **【函数名称】 __create
  32. **【函数功能】 创建
  33. **【参数】
  34. **【返回值】
  35. ****************************************************************/
  36. bool CNetClient::__create( void )
  37. {
  38. ASSERT(m_Socket == INVALID_SOCKET);
  39. m_Socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
  40. if(m_Socket == INVALID_SOCKET)
  41. return false;
  42. else
  43. return true;
  44. }
  45. /*****************************************************************
  46. **【函数名称】 __connect
  47. **【函数功能】 连接服务器
  48. **【参数】
  49. **【返回值】
  50. ****************************************************************/
  51. bool CNetClient::__connect( LPCTSTR FarAddr, int FarPort )
  52. {
  53. SOCKADDR_IN sockAddr;
  54. memset(&sockAddr,0,sizeof(sockAddr));
  55. sockAddr.sin_family = AF_INET;
  56. sockAddr.sin_addr.s_addr = inet_addr(FarAddr);
  57. if (sockAddr.sin_addr.s_addr == INADDR_NONE)
  58. {
  59. LPHOSTENT lphost;
  60. lphost = gethostbyname(FarAddr);
  61. if (lphost != NULL)
  62. sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
  63. else
  64. return false;
  65. }
  66. sockAddr.sin_port = htons((u_short)FarPort);
  67. if(connect(m_Socket, (sockaddr*)&sockAddr, sizeof(sockAddr)) == 0)
  68. {
  69. m_pParent->onConnEstablished(this);
  70. return true;
  71. }
  72. else
  73. {
  74. m_pParent->onConnFailed(this);
  75. return false;
  76. }
  77. }
  78. /*****************************************************************
  79. **【函数名称】 __send
  80. **【函数功能】 发送数据
  81. **【参数】
  82. **【返回值】
  83. ****************************************************************/
  84. bool CNetClient::__send( UCHAR a_szBuf[], UINT a_BufLen )
  85. {
  86. UINT nHasSend = 0;
  87. while(nHasSend < a_BufLen)
  88. {
  89. int nSend = send(m_Socket, (LPCTSTR)&a_szBuf[nHasSend], a_BufLen - nHasSend, 0);
  90. if(nSend > 0)
  91. {
  92. nHasSend += nSend;
  93. }
  94. else
  95. {
  96. if(WSAGetLastError() == WSAEWOULDBLOCK) // 阻塞
  97. Sleep(10);
  98. else
  99. return false;
  100. }
  101. } // end while
  102. return true;
  103. }
  104. /*****************************************************************
  105. **【函数名称】 doJob
  106. **【函数功能】 开始解析接收的数据并投递接收请求
  107. **【参数】
  108. **【返回值】
  109. ****************************************************************/
  110. void CNetClient::doJob( OVERLAPPED* pOverLapped, DWORD BytesTransfered )
  111. {
  112. TRACE(_T("recv: %d @CNetClient::doJob\r\n"), BytesTransfered);
  113. if(m_DropFlag)
  114. return;
  115. if(BytesTransfered == 0)
  116. {
  117. onDisconnect();
  118. return;
  119. }
  120. // 对接收的数据进行处理
  121. m_HasRead += BytesTransfered;
  122. // 如果已经接收到完整的包头
  123. while(m_HasRead > PDU_HEAD_LEN) // 有可能一次接收到多个完整命令
  124. {
  125. CPduEntityHead pduHead;
  126. // 解析PDU数据包头
  127. if(!pduHead.Decode((UCHAR*)m_szBuffer))
  128. {
  129. __resetBuffer(); // 如果解析失败,清除缓冲区
  130. break;
  131. } // end if
  132. // 如果数据包完整(HEAD + DATA)
  133. if(m_HasRead >= (PDU_HEAD_LEN + pduHead.GetDataLen()))
  134. {
  135. // 拷贝当前要处理的数据到临时缓冲区
  136. UCHAR szTmpBuf[PDU_MAX_DATA_LEN] = { 0 };
  137. memcpy_s(szTmpBuf, PDU_MAX_DATA_LEN, m_szBuffer, PDU_HEAD_LEN + pduHead.GetDataLen());
  138. // 清除已处理的数据(数据前移)
  139. m_HasRead = m_HasRead - (PDU_HEAD_LEN + pduHead.GetDataLen());
  140. memmove_s(m_szBuffer, PDU_BUFFER_LEN, &m_szBuffer[PDU_HEAD_LEN + pduHead.GetDataLen()], m_HasRead);
  141. ZeroMemory(&m_szBuffer[m_HasRead], PDU_BUFFER_LEN - m_HasRead);
  142. // 对数据进行处理
  143. CPduEntity pduEntity(&pduHead, &szTmpBuf[PDU_HEAD_LEN]);
  144. pduEntity.SetAssoSocket(m_Socket);
  145. m_pParent->onRecvCommand(&pduEntity);
  146. }
  147. else
  148. {
  149. break; // 如果当前数据不是一个完整数据包,退出循环
  150. } // end if
  151. } // end while
  152. ready4Recv();
  153. }
  154. /*****************************************************************
  155. **【函数名称】 isAlive
  156. **【函数功能】 客户端是否断链
  157. **【参数】
  158. **【返回值】
  159. ****************************************************************/
  160. bool CNetClient::isAlive( void )
  161. {
  162. return monitor();
  163. }
  164. /*****************************************************************
  165. **【函数名称】 __onDisconnect
  166. **【函数功能】 网络断连的处理函数
  167. **【参数】
  168. **【返回值】
  169. ****************************************************************/
  170. void CNetClient::onDisconnect( void )
  171. {
  172. TRACE(_T("@CNetClient::onDisconnect\r\n"));
  173. if(m_DropFlag)
  174. return;
  175. _close();
  176. __create();
  177. __resetBuffer();
  178. m_pParent->onConnFailed(this);
  179. }
  180. /*****************************************************************
  181. **【函数名称】 connect2Server
  182. **【函数功能】 连接到SERVER端
  183. **【参数】
  184. **【返回值】
  185. ****************************************************************/
  186. bool CNetClient::connect2Server( const CString& a_FarIp, int a_FarPort, PDU_DEV_TYPE a_FarType, int a_FarId )
  187. {
  188. if(!__create())
  189. return false;
  190. m_Assistant.setFarLinkInfo(a_FarIp, a_FarPort);
  191. m_Assistant.setFarDevInfo(a_FarType, a_FarId);
  192. if(__connect(a_FarIp, a_FarPort))
  193. return true;
  194. else
  195. return false;
  196. }
  197. /*****************************************************************
  198. **【函数名称】 regist
  199. **【函数功能】 向服务器注册
  200. **【参数】
  201. **【返回值】
  202. ****************************************************************/
  203. bool CNetClient::regist( void )
  204. {
  205. // 生成注册命令
  206. CPduEntity reg(PDU_CMD_REG);
  207. PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN;
  208. int DevId = -1;
  209. m_Assistant.getFarDevInfo(DevType, DevId);
  210. reg.SetPeerDevInfo(DevType, DevId); // 填充接收方信息
  211. m_pParent->getLocalInfo(DevType, DevId);
  212. reg.SetLocalDevInfo(DevType, DevId); // 填充发送方信息
  213. // 发送注册命令
  214. return sendDirectly(&reg);
  215. }
  216. /*****************************************************************
  217. **【函数名称】 monitor
  218. **【函数功能】 发送心跳监听
  219. **【参数】
  220. **【返回值】
  221. ****************************************************************/
  222. bool CNetClient::monitor( void )
  223. {
  224. CPduEntity Monitor(PDU_CMD_LISTEN);
  225. PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN;
  226. int DevId = -1;
  227. m_Assistant.getFarDevInfo(DevType, DevId);
  228. Monitor.SetPeerDevInfo(DevType, DevId); // 填充接收方信息
  229. m_pParent->getLocalInfo(DevType, DevId);
  230. Monitor.SetLocalDevInfo(DevType, DevId); // 填充发送方信息
  231. // 发送心跳监听
  232. return sendDirectly(&Monitor);
  233. }
  234. /*****************************************************************
  235. **【函数名称】 sendDirectly
  236. **【函数功能】 直接发送PDU命令
  237. **【参数】 a_pCmd 要发送的命令实体
  238. **【返回值】
  239. ****************************************************************/
  240. bool CNetClient::sendDirectly( CPduEntity* a_pCmd )
  241. {
  242. ASSERT(m_Socket != INVALID_SOCKET);
  243. // 生成要发送的数据缓冲区
  244. UCHAR szBuf[PDU_HEAD_LEN + PDU_MAX_DATA_LEN];
  245. ZeroMemory(szBuf, PDU_HEAD_LEN + PDU_MAX_DATA_LEN);
  246. int nLen = a_pCmd->CreatePackge(szBuf);
  247. // 发送
  248. return __send(szBuf, nLen);
  249. }
  250. /*****************************************************************
  251. **【函数名称】 sendPdu
  252. **【函数功能】 发送PDU命令
  253. **【参数】 a_pCmd 要发送的命令实体
  254. **【返回值】
  255. ****************************************************************/
  256. bool CNetClient::sendPdu( CPduEntity* a_pCmd )
  257. {
  258. PDU_DEV_TYPE DevType;
  259. int DevId;
  260. m_Assistant.getFarDevInfo(DevType, DevId);
  261. a_pCmd->SetPeerDevInfo(DevType, DevId);
  262. return sendDirectly(a_pCmd);
  263. }
  264. /*****************************************************************
  265. **【函数名称】 ready4Recv
  266. **【函数功能】 准备接收数据
  267. **【参数】
  268. **【返回值】
  269. ****************************************************************/
  270. bool CNetClient::ready4Recv( void )
  271. {
  272. // 初始化变量
  273. DWORD dwFlags = MSG_PARTIAL;
  274. DWORD dwBytes = 0;
  275. m_WsaBuf.buf = &m_szBuffer[m_HasRead];
  276. m_WsaBuf.len = PDU_BUFFER_LEN - m_HasRead;
  277. ZeroMemory(&m_Overlapped, sizeof(OVERLAPPED));
  278. // 投递WSARecv请求
  279. int nBytesRecv = WSARecv(m_Socket, &m_WsaBuf, 1, &dwBytes, &dwFlags, &m_Overlapped, NULL );
  280. if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
  281. {
  282. TRACE(_T("WSARecv error@ CNetClient::ready4Recv\r\n"));
  283. onDisconnect();
  284. return false;
  285. }
  286. return true;
  287. }
  288. /*****************************************************************
  289. **【函数名称】 drop
  290. **【函数功能】 丢弃此客户端
  291. **【参数】
  292. **【返回值】
  293. ****************************************************************/
  294. void CNetClient::drop( void )
  295. {
  296. m_DropFlag = true;
  297. _close();
  298. }
  299. /*****************************************************************
  300. **【函数名称】 getLocalInfo
  301. **【函数功能】 获取本端设备类型及ID
  302. **【参数】
  303. **【返回值】
  304. ****************************************************************/
  305. void CNetClient::getLocalInfo( PDU_DEV_TYPE& a_DevType, int& a_DevId ) const
  306. {
  307. m_pParent->getLocalInfo(a_DevType, a_DevId);
  308. }