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

NetLinkMain.cpp 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. #include "StdAfx.h"
  2. #include "NetLinkMain.h"
  3. #include "NetClient.h"
  4. #include "NetServer.h"
  5. #include "PduEntity.h"
  6. SINGLETON_IMPLEMENT(CNetLinkMain)
  7. /*****************************************************************
  8. **【函数名称】 getCommInstance
  9. **【函数功能】 得到消息通讯接口实例
  10. **【参数】
  11. **【返回值】
  12. ****************************************************************/
  13. IPduComm* CInterfaceWindow::getIocpCommInstance()
  14. {
  15. return &CNetLinkMain::GetInstance();
  16. }
  17. /*****************************************************************
  18. **【函数名称】 getLinkInstance
  19. **【函数功能】 得到消息通讯接口实例
  20. **【参数】
  21. **【返回值】
  22. ****************************************************************/
  23. IPduLink* CInterfaceWindow::getIocpLinkInstance()
  24. {
  25. return &CNetLinkMain::GetInstance();
  26. }
  27. CNetLinkMain::CNetLinkMain(void) : m_pServer(NULL), m_hIocp(INVALID_HANDLE_VALUE), m_phWorkerThreads(NULL), m_ThreadCount(0), m_ThreadStop(true),
  28. m_DevType(PDU_DEV_TYPE_UNKNOWN), m_DevId(0)
  29. {
  30. WSADATA wsaData;
  31. if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
  32. AfxMessageBox("WSAStartup执行失败");
  33. }
  34. CNetLinkMain::~CNetLinkMain(void)
  35. {
  36. StopAll();
  37. }
  38. /*****************************************************************
  39. **【函数名称】 __workerThread
  40. **【函数功能】 为IOCP请求服务的工作者线程
  41. **【参数】
  42. **【返回值】
  43. ****************************************************************/
  44. DWORD WINAPI CNetLinkMain::__workerThread( LPVOID lpParam )
  45. {
  46. CNetLinkMain* pSelf = (CNetLinkMain*)lpParam;
  47. ASSERT(pSelf != NULL);
  48. OVERLAPPED* pOverlapped = NULL;
  49. CSocketBase* pNetEnd = NULL;
  50. DWORD dwBytesTransfered = 0;
  51. BOOL Res;
  52. while(!pSelf->m_ThreadStop)
  53. {
  54. // 循环处理请求,知道接收到Shutdown信息为止
  55. Res = GetQueuedCompletionStatus(pSelf->m_hIocp, &dwBytesTransfered, (PULONG_PTR)&pNetEnd, &pOverlapped, INFINITE);
  56. // 如果收到的是退出标志,则直接退出
  57. if(VAL_THREAD_EXIT_CODE == pNetEnd)
  58. break;
  59. // 判断是否出现了错误
  60. if(!Res)
  61. {
  62. if(!pSelf->__handleNetEndError(pNetEnd, GetLastError()))
  63. {
  64. ASSERT(FALSE);
  65. // break;
  66. }
  67. continue;
  68. }
  69. else
  70. {
  71. if(dwBytesTransfered == 0 && !pSelf->__isClientExisted(pNetEnd))
  72. continue;
  73. pNetEnd->doJob(pOverlapped, dwBytesTransfered);
  74. }
  75. pSelf->m_ClientContainer.clearClientDeleted();
  76. }
  77. TRACE(_T("Thread quit @CNetLinkMain::_workerThread\r\n"));
  78. return 0;
  79. }
  80. /*****************************************************************
  81. **【函数名称】 __handleNetEndError
  82. **【函数功能】 处理网络端错误
  83. **【参数】
  84. **【返回值】
  85. ****************************************************************/
  86. bool CNetLinkMain::__handleNetEndError( CSocketBase* pNetEnd, DWORD ErrorCode )
  87. {
  88. switch(ErrorCode)
  89. {
  90. case WAIT_TIMEOUT: // 超时,继续等待
  91. {
  92. return true;
  93. }
  94. break;
  95. case ERROR_CONNECTION_ABORTED: // 连接被中断
  96. {
  97. return true; // 此处pNetEnd往往是为无效野指针,故而不能调用pNetEnd->onDisconnect()。
  98. }
  99. break;
  100. case ERROR_NETNAME_DELETED: // 客户端异常退出
  101. case ERROR_PORT_UNREACHABLE: // 没有任何服务正在远程系统上的目标网络终结点上操作
  102. default:
  103. {
  104. if(pNetEnd != NULL)
  105. {
  106. pNetEnd->onDisconnect();
  107. return true;
  108. }
  109. else
  110. return false; // IO错误,返回false退出工作线程
  111. }
  112. }
  113. }
  114. /*****************************************************************
  115. **【函数名称】 __getCountOfProcessors
  116. **【函数功能】 获得本机的处理器数量
  117. **【参数】
  118. **【返回值】
  119. ****************************************************************/
  120. int CNetLinkMain::__getCountOfProcessors( void )
  121. {
  122. SYSTEM_INFO si;
  123. GetSystemInfo(&si);
  124. return si.dwNumberOfProcessors;
  125. }
  126. /*****************************************************************
  127. **【函数名称】 __getThreadCount
  128. **【函数功能】 获得服务器端线程数量
  129. **【参数】
  130. **【返回值】
  131. ****************************************************************/
  132. int CNetLinkMain::__getThreadCount( PDU_DEV_TYPE a_LocalType )
  133. {
  134. int Count = 0;
  135. switch(a_LocalType)
  136. {
  137. case PDU_DEV_TYPE_CTI:
  138. case PDU_DEV_TYPE_SC_SERVER:
  139. Count = __getCountOfProcessors();
  140. break;
  141. case PDU_DEV_TYPE_ACD:
  142. Count = VAL_THREAD_PER_PROCESSOR * __getCountOfProcessors();
  143. break;
  144. default:
  145. Count = __getCountOfProcessors();
  146. break;
  147. }
  148. return Count;
  149. }
  150. /*****************************************************************
  151. **【函数名称】 __setupIocp
  152. **【函数功能】 创建完成端口服务端模式
  153. **【参数】
  154. **【返回值】
  155. ****************************************************************/
  156. bool CNetLinkMain::__setupIocp( PDU_DEV_TYPE a_LocalType )
  157. {
  158. // 建立完成端口
  159. m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
  160. if ( NULL == m_hIocp)
  161. return false;
  162. // 根据本机中的处理器数量,建立对应的线程数
  163. m_ThreadCount = __getThreadCount(a_LocalType);
  164. // 为工作者线程初始化句柄
  165. m_phWorkerThreads = new HANDLE[m_ThreadCount];
  166. m_ThreadStop = false;
  167. // 根据计算出来的数量建立工作者线程
  168. DWORD ThreadID;
  169. for (int i = 0; i < m_ThreadCount; i++)
  170. {
  171. m_phWorkerThreads[i] = ::CreateThread(0, 0, __workerThread, (void *)this, 0, &ThreadID);
  172. }
  173. TRACE(_T("ThreadCount: %d @CNetLinkMain::__setupIocp\r\n"), m_ThreadCount);
  174. return true;
  175. }
  176. /*****************************************************************
  177. **【函数名称】 __setLocalInfo
  178. **【函数功能】 设定PDU本端设备类型及ID
  179. **【参数】 a_nDevType 本端设备类型
  180. a_nDevId 本端设备ID
  181. **【返回值】
  182. ****************************************************************/
  183. void CNetLinkMain::__setLocalInfo( PDU_DEV_TYPE a_nDevType, int a_nDevId )
  184. {
  185. m_DevType = a_nDevType;
  186. m_DevId = a_nDevId;
  187. }
  188. /*****************************************************************
  189. **【函数名称】 __setLinkContent
  190. **【函数功能】 生成连接信息内容
  191. **【参数】 a_nLinkInfo SOCKET连接状态
  192. a_pClient 关联的客户端
  193. **【返回值】
  194. ****************************************************************/
  195. void CNetLinkMain::__setLinkContent( PduLinkContent& linkContent, PDU_LINK_STATE a_nLinkInfo, CNetClient* a_pClient )
  196. {
  197. memset(&linkContent, 0, sizeof(PduLinkContent));
  198. CString strIp = _T("");
  199. linkContent.nLocalType = m_DevType;
  200. linkContent.nLocalId = m_DevId;
  201. linkContent.nLinkState = a_nLinkInfo;
  202. a_pClient->getFarLinkInfo(strIp, linkContent.nFarPort);
  203. a_pClient->getFarDevInfo(linkContent.nFarType, linkContent.nFarId);
  204. lstrcpy(linkContent.szFarIp, strIp);
  205. }
  206. /*****************************************************************
  207. **【函数名称】 __setLinkContent
  208. **【函数功能】 生成连接信息内容
  209. **【参数】 a_nLinkInfo SOCKET连接状态
  210. a_pClient 关联的客户端
  211. **【返回值】
  212. ****************************************************************/
  213. void CNetLinkMain::__setLinkContent( PduLinkContent& linkContent, CNetClient* a_pClient )
  214. {
  215. memset(&linkContent, 0, sizeof(PduLinkContent));
  216. CString strIp = _T("");
  217. linkContent.nLocalType = m_DevType;
  218. linkContent.nLocalId = m_DevId;
  219. a_pClient->getFarLinkInfo(strIp, linkContent.nFarPort);
  220. a_pClient->getFarDevInfo(linkContent.nFarType, linkContent.nFarId);
  221. lstrcpy(linkContent.szFarIp, strIp);
  222. }
  223. /*****************************************************************
  224. **【函数名称】 __isClientExisted
  225. **【函数功能】 判断客户端是否还存在
  226. **【参数】
  227. **【返回值】
  228. ****************************************************************/
  229. bool CNetLinkMain::__isClientExisted( CSocketBase* pClient )
  230. {
  231. if(pClient == m_pServer)
  232. return true;
  233. return m_ClientContainer.getClient((CNetClient*)pClient) != NULL;
  234. }
  235. /*****************************************************************
  236. **【函数名称】 Send
  237. **【函数功能】 发送PDU命令
  238. **【参数】 a_pCmd 要发送的命令实体
  239. a_nDestType 消息要发送的目标设备类型
  240. a_nDestId 消息要发送的目标设备ID
  241. **【返回值】
  242. ****************************************************************/
  243. BOOL CNetLinkMain::Send( CPduEntity* a_pCmd, PDU_DEV_TYPE a_nDestType, int a_nDestId )
  244. {
  245. CNetClient* pClient = NULL;
  246. // 对注册命令的特殊处理
  247. if(a_pCmd->GetCmdType() == PDU_CMD_REG && a_pCmd->GetIsExecReturn())
  248. {
  249. // 查找要发送命令的连接
  250. pClient = m_ClientContainer.getClient(a_pCmd->GetAssoSocket());
  251. if(pClient == NULL)
  252. return FALSE;
  253. // 触发注册事件
  254. if(a_pCmd->GetDataBool(0))
  255. {
  256. pClient->setFarDevInfo(a_nDestType, a_nDestId);
  257. onConnRegistOK(pClient);
  258. }
  259. else
  260. {
  261. onConnRegistFailed(pClient);
  262. } // end if
  263. }
  264. else
  265. {
  266. // 查找要发送命令的连接
  267. pClient = m_ClientContainer.getClient(a_nDestType, a_nDestId);
  268. if(pClient == NULL)
  269. return FALSE;
  270. } // end if
  271. // 发送命令
  272. a_pCmd->SetLocalDevInfo(m_DevType, m_DevId); // 填充发送方信息
  273. a_pCmd->SetPeerDevInfo(a_nDestType, a_nDestId); // 填充接收方信息
  274. return pClient->sendDirectly(a_pCmd) ? TRUE : FALSE;
  275. }
  276. /*****************************************************************
  277. **【函数名称】 Send2All
  278. **【函数功能】 向所有注册过的客户端发送PDU
  279. **【参数】
  280. **【返回值】
  281. ****************************************************************/
  282. void CNetLinkMain::Send2All( CPduEntity* a_pCmd )
  283. {
  284. // 发送命令
  285. a_pCmd->SetLocalDevInfo(m_DevType, m_DevId); // 填充发送方信息
  286. m_ClientContainer.send2All(a_pCmd);
  287. }
  288. /*****************************************************************
  289. **【函数名称】 getLocalInfo
  290. **【函数功能】 读取本端设备类型及ID
  291. **【参数】
  292. **【返回值】 a_DevType 本端设备类型
  293. a_DevId 本端设备ID
  294. ****************************************************************/
  295. void CNetLinkMain::getLocalInfo( PDU_DEV_TYPE& a_DevType, int& a_DevId )
  296. {
  297. a_DevType = m_DevType;
  298. a_DevId = m_DevId;
  299. }
  300. /*****************************************************************
  301. **【函数名称】 GetLinkInfo
  302. **【函数功能】 获取指定连接的网络信息
  303. **【参数】 OUT a_strIp 指定连接的对端IP
  304. OUT a_nPort 指定连接的对端PORT
  305. IN a_nType 要查询的连接类型
  306. IN a_nId 要查询的连接ID
  307. **【返回值】
  308. ****************************************************************/
  309. BOOL CNetLinkMain::GetLinkInfo( CString& a_strIp, int& a_nPort, PDU_DEV_TYPE a_nType, int a_nId )
  310. {
  311. // 查找连接
  312. CNetClient* pClient = m_ClientContainer.getClient(a_nType, a_nId);
  313. if(pClient == NULL)
  314. return FALSE;
  315. // 获取连接的网络信息
  316. pClient->getFarLinkInfo(a_strIp, a_nPort);
  317. return TRUE;
  318. }
  319. /*****************************************************************
  320. **【函数名称】 GetPeerIp
  321. **【函数功能】 获取PDU命令的发送方IP
  322. **【参数】 OUT a_strIp 发送当前PDU命令的对端IP
  323. IN a_pCmd 当前接收到的PDU命令
  324. **【返回值】
  325. ****************************************************************/
  326. BOOL CNetLinkMain::GetPeerIp( CString& a_strIp, CPduEntity* a_pCmd )
  327. {
  328. CNetClient* pClient = m_ClientContainer.getClient(a_pCmd->GetAssoSocket());
  329. if(pClient == NULL)
  330. return FALSE;
  331. // 获取连接的网络信息
  332. int nPort = 0;
  333. pClient->getFarLinkInfo(a_strIp, nPort);
  334. return TRUE;
  335. }
  336. /*****************************************************************
  337. **【函数名称】 CreatePduServer
  338. **【函数功能】 创建PDU通讯服务器
  339. **【参数】 a_nListenPort SOCKET监听端口
  340. a_nLocalType 服务器设备类型
  341. a_nLocalId 服务器设备ID
  342. **【返回值】
  343. ****************************************************************/
  344. BOOL CNetLinkMain::CreatePduServer( int a_nListenPort, PDU_DEV_TYPE a_nLocalType, int a_nLocalId )
  345. {
  346. if(!__setupIocp(a_nLocalType))
  347. return FALSE;
  348. m_pServer = new CNetServer(this);
  349. ASSERT(m_pServer != NULL);
  350. // 启动SERVER
  351. if(m_pServer->create(a_nListenPort))
  352. {
  353. __setLocalInfo(a_nLocalType, a_nLocalId);
  354. return TRUE;
  355. }
  356. else
  357. {
  358. delete m_pServer;
  359. m_pServer = NULL;
  360. } // end if
  361. return FALSE;
  362. }
  363. /*****************************************************************
  364. **【函数名称】 CreatePduClient
  365. **【函数功能】 创建PDU通讯客户端
  366. **【参数】 a_strFarIp 要连接的服务器IP
  367. a_nFarPort 要连接的服务器端口号
  368. a_nLocalType 本端设备类型
  369. a_nLocalId 本端设备ID
  370. a_nFarType 对端设备类型
  371. a_nFarId 对端设备ID
  372. **【返回值】 TRUE 启动连接成功
  373. FALSE 启动连接失败
  374. ****************************************************************/
  375. BOOL CNetLinkMain::CreatePduClient( CString a_strFarIp, int a_nFarPort, PDU_DEV_TYPE a_nLocalType, int a_nLocalId, PDU_DEV_TYPE a_nFarType, int a_nFarId, bool IsAutoReconnect )
  376. {
  377. // 如果已存在到对端的连接
  378. CNetClient* pClient = m_ClientContainer.getClient(a_nFarType, a_nFarId);
  379. if(pClient != NULL)
  380. return FALSE;
  381. // 开始连接
  382. pClient = new CNetClient(this, PDU_LINK_TYPE_CLIENT, IsAutoReconnect);
  383. m_ClientContainer.insertClient(pClient);
  384. __setLocalInfo(a_nLocalType, a_nLocalId);
  385. if(pClient->connect2Server(a_strFarIp, a_nFarPort, a_nFarType, a_nFarId))
  386. {
  387. return TRUE;
  388. }
  389. else
  390. {
  391. return FALSE;
  392. } // end if
  393. }
  394. /*****************************************************************
  395. **【函数名称】 ClosePduClient
  396. **【函数功能】 关闭PDU通讯客户端
  397. **【参数】 a_nFarType 对端设备类型
  398. a_nFarId 对端设备ID
  399. **【返回值】 TRUE 启动连接成功
  400. FALSE 启动连接失败
  401. ****************************************************************/
  402. BOOL CNetLinkMain::ClosePduClient( PDU_DEV_TYPE a_nFarType, int a_nFarId )
  403. {
  404. return m_ClientContainer.removeClient(a_nFarType, a_nFarId) ? TRUE : FALSE;
  405. }
  406. /*****************************************************************
  407. **【函数名称】 RegistPduLinkProc
  408. **【函数功能】 订阅连接管理事件
  409. **【参数】 a_pPduLinkProc 要对事件进行处理的接口类
  410. bIsInsert 添加/删除定阅
  411. **【返回值】
  412. ****************************************************************/
  413. BOOL CNetLinkMain::RegistPduLinkProc( IPduLinkProc* a_pPduLinkProc, BOOL bIsInsert )
  414. {
  415. return m_EventHost.RegLinkProc(a_pPduLinkProc, bIsInsert);
  416. }
  417. /*****************************************************************
  418. **【函数名称】 RegistPduCommProc
  419. **【函数功能】 订阅消息通知事件
  420. **【参数】 a_pPduCommProc 要对事件进行处理的接口类
  421. bIsInsert 添加/删除定阅
  422. **【返回值】
  423. ****************************************************************/
  424. BOOL CNetLinkMain::RegistPduCommProc( IPduCommProc* a_pPduCommProc, BOOL bIsInsert )
  425. {
  426. return m_EventHost.RegCommProc(a_pPduCommProc, bIsInsert);
  427. }
  428. /*****************************************************************
  429. **【函数名称】 waitNetEnd
  430. **【函数功能】 等候网络一端的连接和数据
  431. **【参数】 pNetEnd:网络一端
  432. **【返回值】
  433. ****************************************************************/
  434. bool CNetLinkMain::waitNetEnd( CSocketBase* pNetEnd )
  435. {
  436. ASSERT(pNetEnd != NULL);
  437. // 将用于和客户端通信的SOCKET绑定到完成端口中
  438. return CreateIoCompletionPort((HANDLE)pNetEnd->assoSocket(), m_hIocp, (DWORD)pNetEnd, 0) != NULL;
  439. }
  440. /*****************************************************************
  441. **【函数名称】 onConnEstablished
  442. **【函数功能】 初始连接建立的后续处理
  443. **【参数】
  444. **【返回值】
  445. ****************************************************************/
  446. void CNetLinkMain::onConnEstablished( CNetClient* a_pClient )
  447. {
  448. ASSERT(a_pClient != NULL);
  449. if(!waitNetEnd(a_pClient) || !a_pClient->ready4Recv())
  450. {
  451. delete a_pClient;
  452. TRACE(_T("{!waitNetEnd(a_pClient) || !a_pClient->ready4Recv()} @CNetLinkMain::onConnEstablished\r\n"));
  453. return;
  454. }
  455. // 对SOCKET容器的处理
  456. PDU_LINK_STATE nLinkState = m_ClientContainer.onConnEstablished(a_pClient);
  457. // 对事件观查者的处理
  458. PduLinkContent linkContent;
  459. __setLinkContent(linkContent, nLinkState, a_pClient);
  460. m_EventHost.OnLinkStateChanged(linkContent);
  461. // 对SOCKET监控的处理
  462. a_pClient->onConnEstablished();
  463. }
  464. /*****************************************************************
  465. **【函数名称】 onConnFailed
  466. **【函数功能】 初连接断开/失败的后续处理
  467. **【参数】
  468. **【返回值】
  469. ****************************************************************/
  470. void CNetLinkMain::onConnFailed( CNetClient* a_pClient )
  471. {
  472. // 对SOCKET监控的处理
  473. a_pClient->onConnFailed();
  474. PduLinkContent linkContent;
  475. __setLinkContent(linkContent, a_pClient);
  476. // 对SOCKET容器的处理
  477. linkContent.nLinkState = m_ClientContainer.onConnFailed(a_pClient);
  478. // 对事件观查者的处理
  479. m_EventHost.OnLinkStateChanged(linkContent);
  480. }
  481. /*****************************************************************
  482. **【函数名称】 onConnRegistOK
  483. **【函数功能】 连接注册成功的后续处理
  484. **【参数】
  485. **【返回值】
  486. ****************************************************************/
  487. void CNetLinkMain::onConnRegistOK( CNetClient* a_pClient )
  488. {
  489. // 对SOCKET监控的处理
  490. a_pClient->onConnRegistOK();
  491. // 对SOCKET容器的处理
  492. PDU_LINK_STATE nLinkState = m_ClientContainer.onConnRegistOK(a_pClient);
  493. // 对事件观查者的处理
  494. PduLinkContent linkContent;
  495. __setLinkContent(linkContent, nLinkState, a_pClient);
  496. m_EventHost.OnLinkStateChanged(linkContent);
  497. }
  498. /*****************************************************************
  499. **【函数名称】 onConnRegistFailed
  500. **【函数功能】 连接注册失败的后续处理
  501. **【参数】
  502. **【返回值】
  503. ****************************************************************/
  504. void CNetLinkMain::onConnRegistFailed( CNetClient* a_pClient )
  505. {
  506. // 对SOCKET监控的处理
  507. a_pClient->onConnRegistFailed();
  508. // 对SOCKET容器的处理
  509. PDU_LINK_STATE nLinkState = m_ClientContainer.onConnRegistFailed(a_pClient);
  510. // 对事件观查者的处理
  511. PduLinkContent linkContent;
  512. __setLinkContent(linkContent, nLinkState, a_pClient);
  513. m_EventHost.OnLinkStateChanged(linkContent);
  514. }
  515. /*****************************************************************
  516. **【函数名称】 onRecvCommand
  517. **【函数功能】 命令接收的处理
  518. **【参数】 a_pCmd 当前接收到的命令实体
  519. **【返回值】
  520. ****************************************************************/
  521. void CNetLinkMain::onRecvCommand( CPduEntity* a_pCmd )
  522. {
  523. // 接收端校验
  524. ASSERT((a_pCmd->GetPeerDevId() == (ULONG)m_DevId && a_pCmd->GetPeerDevType() == (ULONG)m_DevType));
  525. // 对注册命令的特殊处理
  526. if(a_pCmd->GetCmdType() == PDU_CMD_REG && a_pCmd->GetIsExecReturn())
  527. {
  528. // 查找要接收命令的连接
  529. CNetClient* pClient = m_ClientContainer.getClient(a_pCmd->GetAssoSocket());
  530. if(pClient == NULL)
  531. return;
  532. // 触发注册事件
  533. if(a_pCmd->GetDataBool(0))
  534. {
  535. onConnRegistOK(pClient);
  536. }
  537. else
  538. {
  539. onConnRegistFailed(pClient);
  540. } // end if
  541. } // end if
  542. // 对事件观查者的处理
  543. m_EventHost.OnRecvCommand(a_pCmd);
  544. }
  545. /*****************************************************************
  546. **【函数名称】 StopAll
  547. **【函数功能】 停止
  548. **【参数】
  549. **【返回值】
  550. ****************************************************************/
  551. void CNetLinkMain::StopAll( void )
  552. {
  553. if(!m_ThreadStop)
  554. {
  555. m_ThreadStop = true;
  556. for (int i = 0; i < m_ThreadCount; ++i)
  557. {
  558. // 通知所有的完成端口操作退出
  559. PostQueuedCompletionStatus(m_hIocp, 0, (DWORD)VAL_THREAD_EXIT_CODE, NULL);
  560. }
  561. // 等待所有的客户端资源退出
  562. WaitForMultipleObjects(m_ThreadCount, m_phWorkerThreads, TRUE, INFINITE);
  563. // 释放工作者线程句柄指针
  564. for( int i=0;i<m_ThreadCount;i++ )
  565. {
  566. CloseHandle(m_phWorkerThreads[i]);
  567. }
  568. delete []m_phWorkerThreads;
  569. // 关闭IOCP句柄
  570. CloseHandle(m_hIocp);
  571. m_hIocp = INVALID_HANDLE_VALUE;
  572. RELEASE(m_pServer)
  573. }
  574. m_ClientContainer.release();
  575. }