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

PduSocket.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. // ..\..\..\Public\PduLink\PduSocket.cpp : 实现文件
  2. //
  3. #include "StdAfx.h"
  4. #include "PduSocket.h"
  5. #include "PduSocketMonitor.h"
  6. #include "PduMain.h"
  7. #include "PduEntity.h"
  8. #include "PduEntityHead.h"
  9. // CPduSocket
  10. CPduSocket::CPduSocket(CPduMain* a_pParent, PDU_LINK_TYPE a_nLinkType, bool IsAutoReconnect)
  11. {
  12. // 初始化监控信息
  13. m_pSocketMonitor = new CPduSocketMonitor(IsAutoReconnect);
  14. m_pSocketMonitor->SetLinkType(a_nLinkType); // 连接方式
  15. m_pParent = a_pParent;
  16. // 清空SOCKET数据缓冲区
  17. __InitData();
  18. }
  19. CPduSocket::~CPduSocket()
  20. {
  21. if(m_pSocketMonitor != NULL) delete m_pSocketMonitor;
  22. }
  23. /*****************************************************************
  24. **【函数名称】 __InitData
  25. **【函数功能】 清空SOCKET数据缓冲区
  26. **【参数】
  27. **【返回值】
  28. ****************************************************************/
  29. void CPduSocket::__InitData()
  30. {
  31. m_nHasRead = 0; // 已读取的数据缓冲区长度
  32. memset(m_szPdu, 0, PDU_HEAD_LEN + PDU_MAX_DATA_LEN); // 已读取的缓冲区内容
  33. }
  34. /*****************************************************************
  35. **【函数名称】 GetPeerLinkInfo
  36. **【函数功能】 读取SOCKET连接信息
  37. **【参数】
  38. **【返回值】 a_strIp SOCKET对端IP
  39. a_nPort SOCKET对端PORT
  40. ****************************************************************/
  41. void CPduSocket::GetPeerLinkInfo(CString& a_strIp, int& a_nPort)
  42. {
  43. m_pSocketMonitor->GetPeerLinkInfo(a_strIp, a_nPort);
  44. }
  45. /*****************************************************************
  46. **【函数名称】 GetLinkType
  47. **【函数功能】 得到连接类型
  48. **【参数】
  49. **【返回值】
  50. ****************************************************************/
  51. PDU_LINK_TYPE CPduSocket::GetLinkType()
  52. {
  53. return m_pSocketMonitor->GetLinkType();
  54. }
  55. /*****************************************************************
  56. **【函数名称】 GetPeerDevInfo
  57. **【函数功能】 读取对端设备信息
  58. **【参数】
  59. **【返回值】 a_nDevType 对端设备类型
  60. a_nDevId 对端设备ID
  61. ****************************************************************/
  62. void CPduSocket::GetPeerDevInfo(PDU_DEV_TYPE& a_nDevType, int& a_nDevId)
  63. {
  64. m_pSocketMonitor->GetPeerDevInfo(a_nDevType, a_nDevId);
  65. }
  66. /*****************************************************************
  67. **【函数名称】 SetPeerDevInfo
  68. **【函数功能】 设置对端设备信息
  69. **【参数】 a_nDevType 对端设备类型
  70. a_nDevId 对端设备ID
  71. **【返回值】
  72. ****************************************************************/
  73. void CPduSocket::SetPeerDevInfo(PDU_DEV_TYPE a_nDevType, int a_nDevId)
  74. {
  75. m_pSocketMonitor->SetPeerDevInfo(a_nDevType, a_nDevId);
  76. }
  77. /*****************************************************************
  78. **【函数名称】 GetLocalInfo
  79. **【函数功能】 设置本端设备信息
  80. **【参数】 a_nDevType 本端设备类型
  81. a_nDevId 本端设备ID
  82. **【返回值】
  83. ****************************************************************/
  84. void CPduSocket::GetLocalInfo(PDU_DEV_TYPE& a_nDevType, int& a_nDevId)
  85. {
  86. m_pParent->GetLocalInfo(a_nDevType,a_nDevId);
  87. }
  88. /*****************************************************************
  89. **【函数名称】 ConnectToServer
  90. **【函数功能】 连接到SERVER端
  91. **【参数】
  92. **【返回值】
  93. ****************************************************************/
  94. BOOL CPduSocket::ConnectToServer(const CString& a_strFarIp, int a_nFarPort, PDU_DEV_TYPE a_nFarType, int a_nFarId)
  95. {
  96. if(!Create()) return FALSE;
  97. // 设置监控信息
  98. m_pSocketMonitor->SetPeerLinkInfo(a_strFarIp, a_nFarPort);
  99. m_pSocketMonitor->SetPeerDevInfo(a_nFarType, a_nFarId);
  100. // 开始连接
  101. if(Connect(a_strFarIp, a_nFarPort) == 0)
  102. {
  103. return TRUE;
  104. }
  105. return FALSE;
  106. }
  107. /*****************************************************************
  108. **【函数名称】 Regist
  109. **【函数功能】 注册SOCKET连接
  110. **【参数】
  111. **【返回值】
  112. ****************************************************************/
  113. BOOL CPduSocket::Regist( void )
  114. {
  115. // 生成注册命令
  116. CPduEntity reg(PDU_CMD_REG);
  117. PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN;
  118. int DevId = -1;
  119. m_pSocketMonitor->GetPeerDevInfo(DevType, DevId);
  120. reg.SetPeerDevInfo(DevType, DevId); // 填充接收方信息
  121. m_pParent->GetLocalInfo(DevType, DevId);
  122. reg.SetLocalDevInfo(DevType, DevId); // 填充发送方信息
  123. // 发送注册命令
  124. return SendDirectly(&reg);
  125. }
  126. /*****************************************************************
  127. **【函数名称】 Monitor
  128. **【函数功能】 发送心跳监听
  129. **【参数】
  130. **【返回值】
  131. ****************************************************************/
  132. BOOL CPduSocket::Monitor( void )
  133. {
  134. CPduEntity Monitor(PDU_CMD_LISTEN);
  135. PDU_DEV_TYPE DevType = PDU_DEV_TYPE_UNKNOWN;
  136. int DevId = -1;
  137. m_pSocketMonitor->GetPeerDevInfo(DevType, DevId);
  138. Monitor.SetPeerDevInfo(DevType, DevId); // 填充接收方信息
  139. m_pParent->GetLocalInfo(DevType, DevId);
  140. Monitor.SetLocalDevInfo(DevType, DevId); // 填充发送方信息
  141. // 发送心跳监听
  142. return SendDirectly(&Monitor);
  143. }
  144. /*****************************************************************
  145. **【函数名称】 SendDirectly
  146. **【函数功能】 发送PDU命令
  147. **【参数】 a_pCmd 要发送的命令实体
  148. **【返回值】
  149. ****************************************************************/
  150. BOOL CPduSocket::SendDirectly(CPduEntity* a_pCmd)
  151. {
  152. // 生成要发送的数据缓冲区
  153. UCHAR szBuf[PDU_HEAD_LEN + PDU_MAX_DATA_LEN];
  154. ZeroMemory(szBuf, PDU_HEAD_LEN + PDU_MAX_DATA_LEN);
  155. int nLen = a_pCmd->CreatePackge(szBuf);
  156. // 发送
  157. return __SendBuf(szBuf, nLen);
  158. }
  159. /*****************************************************************
  160. **【函数名称】 SendPdu
  161. **【函数功能】 发送PDU命令
  162. **【参数】 a_pCmd 要发送的命令实体
  163. **【返回值】
  164. ****************************************************************/
  165. BOOL CPduSocket::SendPdu( CPduEntity* a_pCmd )
  166. {
  167. PDU_DEV_TYPE DevType;
  168. int DevId;
  169. m_pSocketMonitor->GetPeerDevInfo(DevType, DevId);
  170. a_pCmd->SetPeerDevInfo(DevType, DevId);
  171. return SendDirectly(a_pCmd);
  172. }
  173. /*****************************************************************
  174. **【函数名称】 OnConnect
  175. **【函数功能】 连接状态事件
  176. **【参数】
  177. **【返回值】
  178. ****************************************************************/
  179. void CPduSocket::OnConnect(int nErrorCode)
  180. {
  181. if(nErrorCode == 0) // 连接建立
  182. {
  183. m_pParent->OnConnEstablished(this);
  184. }
  185. else // 连接失败
  186. {
  187. __InitData(); // 清空SOCKET数据缓冲区
  188. m_pParent->OnConnFailed(this);
  189. } // end if
  190. CAsyncSocket::OnConnect(nErrorCode);
  191. }
  192. /*****************************************************************
  193. **【函数名称】 OnClose
  194. **【函数功能】 关闭事件
  195. **【参数】
  196. **【返回值】
  197. ****************************************************************/
  198. void CPduSocket::OnClose(int nErrorCode)
  199. {
  200. // 必要操作
  201. Close();
  202. Create();
  203. // 清空SOCKET数据缓冲区
  204. __InitData();
  205. m_pParent->OnConnFailed(this); // 连接断开
  206. CAsyncSocket::OnClose(nErrorCode);
  207. }
  208. /*****************************************************************
  209. **【函数名称】 OnReceive
  210. **【函数功能】 消息接收事件
  211. **【参数】
  212. **【返回值】
  213. ****************************************************************/
  214. void CPduSocket::OnReceive(int nErrorCode)
  215. {
  216. // 读数据
  217. int nRead = Receive(&m_szPdu[m_nHasRead], PDU_HEAD_LEN + PDU_MAX_DATA_LEN - m_nHasRead);
  218. if(nRead == SOCKET_ERROR) return;
  219. // 对接收的数据进行处理
  220. m_nHasRead += nRead;
  221. // 如果已经接收到完整的包头
  222. while(m_nHasRead > PDU_HEAD_LEN) // 有可能一次接收到多个完整命令
  223. {
  224. CPduEntityHead pduHead;
  225. // 解析PDU数据包头
  226. if(!pduHead.Decode(m_szPdu))
  227. {
  228. __InitData(); // 如果解析失败,清除缓冲区
  229. break;
  230. } // end if
  231. // 如果数据包完整(HEAD + DATA)
  232. if(m_nHasRead >= (PDU_HEAD_LEN + pduHead.GetDataLen()))
  233. {
  234. // 拷贝当前要处理的数据到临时缓冲区
  235. UCHAR szTmpBuf[PDU_MAX_DATA_LEN];
  236. ZeroMemory(szTmpBuf, PDU_MAX_DATA_LEN);
  237. memcpy_s(szTmpBuf, PDU_MAX_DATA_LEN, m_szPdu, PDU_HEAD_LEN + pduHead.GetDataLen());
  238. // 清除已处理的数据(数据前移)
  239. m_nHasRead = m_nHasRead - (PDU_HEAD_LEN + pduHead.GetDataLen());
  240. memcpy(m_szPdu, &m_szPdu[PDU_HEAD_LEN + pduHead.GetDataLen()], m_nHasRead);
  241. memset(&m_szPdu[m_nHasRead], 0, (PDU_HEAD_LEN + PDU_MAX_DATA_LEN - m_nHasRead));
  242. // 对数据进行处理
  243. CPduEntity pduEntity(&pduHead, &szTmpBuf[PDU_HEAD_LEN]);
  244. pduEntity.SetAssoSocket(m_hSocket);
  245. m_pParent->OnRecvCommand(&pduEntity);
  246. }
  247. else
  248. {
  249. break; // 如果当前数据不是一个完整数据包,退出循环
  250. } // end if
  251. } // end while
  252. CAsyncSocket::OnReceive(nErrorCode);
  253. }
  254. /*****************************************************************
  255. **【函数名称】 OnSend
  256. **【函数功能】 消息发送事件
  257. **【参数】
  258. **【返回值】
  259. ****************************************************************/
  260. void CPduSocket::OnSend(int nErrorCode)
  261. {
  262. // TODO: 在此添加专用代码和/或调用基类
  263. CAsyncSocket::OnSend(nErrorCode);
  264. }
  265. /*****************************************************************
  266. **【函数名称】 __SendBuf
  267. **【函数功能】 发送数据缓冲区
  268. **【参数】 a_szBuf[] 内容
  269. a_nBufLen 长度
  270. **【返回值】
  271. ****************************************************************/
  272. BOOL CPduSocket::__SendBuf(UCHAR a_szBuf[], UINT a_nBufLen)
  273. {
  274. UINT nHasSend = 0;
  275. while(nHasSend < a_nBufLen)
  276. {
  277. int nSend = Send(&a_szBuf[nHasSend], a_nBufLen - nHasSend);
  278. if(nSend > 0)
  279. {
  280. nHasSend += nSend;
  281. }
  282. else
  283. {
  284. if(GetLastError() == WSAEWOULDBLOCK) // 阻塞
  285. Sleep(10);
  286. else
  287. return FALSE;
  288. }
  289. }
  290. return TRUE;
  291. }
  292. /*****************************************************************
  293. **【函数名称】 OnConnEstablisthed
  294. **【函数功能】 SOCKET连接建立事件处理
  295. **【参数】
  296. **【返回值】
  297. ****************************************************************/
  298. void CPduSocket::OnConnEstablished()
  299. {
  300. return m_pSocketMonitor->OnConnEstablisthed(this);
  301. }
  302. /*****************************************************************
  303. **【函数名称】 OnConnFailed
  304. **【函数功能】 SOCKET连接断开/失败事件处理
  305. **【参数】
  306. **【返回值】
  307. ****************************************************************/
  308. void CPduSocket::OnConnFailed()
  309. {
  310. return m_pSocketMonitor->OnConnFailed(this);
  311. }
  312. /*****************************************************************
  313. **【函数名称】 OnConnRegistOK
  314. **【函数功能】 SOCKET连接注册成功事件处理
  315. **【参数】
  316. **【返回值】
  317. ****************************************************************/
  318. void CPduSocket::OnConnRegistOK()
  319. {
  320. return m_pSocketMonitor->OnConnRegistOK(this);
  321. }
  322. /*****************************************************************
  323. **【函数名称】 OnConnRegistFailed
  324. **【函数功能】 SOCKET连接注册失败事件处理
  325. **【参数】
  326. **【返回值】
  327. ****************************************************************/
  328. void CPduSocket::OnConnRegistFailed()
  329. {
  330. return m_pSocketMonitor->OnConnRegistFailed(this);
  331. }