PageRenderTime 35ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/core/TTLogic/TcpClientModule_Impl.cpp

https://gitlab.com/yoage/TTWinClient
C++ | 311 lines | 252 code | 46 blank | 13 comment | 25 complexity | 2908c436a735d99380fbec8b51d4a1ff MD5 | raw file
Possible License(s): LGPL-3.0
  1. /*******************************************************************************
  2. * @file TcpClientModule_Impl.cpp 2014\7\29 13:16:48 $
  3. * @author 快刀<kuaidao@mogujie.com>
  4. * @brief
  5. ******************************************************************************/
  6. #include "stdafx.h"
  7. #include "TcpClientModule_Impl.h"
  8. #include "TTLogic/TcpClientSocket.h"
  9. #include "src/base/ImPduClient.h"
  10. #include "utility/utilStrCodeAPI.h"
  11. /******************************************************************************/
  12. NAMESPACE_BEGIN(logic)
  13. ITcpClientModule* getTcpClientModule()
  14. {
  15. return (ITcpClientModule*)logic::GetLogic()->getModule(MODULE_ID_TCPCLIENT);
  16. }
  17. namespace
  18. {
  19. UInt16 g_seqNum = 0;
  20. }
  21. // -----------------------------------------------------------------------------
  22. // TcpClientModule_Impl: Public, Constructor
  23. TcpClientModule_Impl::TcpClientModule_Impl()
  24. :m_tcpClientState(TCPCLIENT_STATE_OK)
  25. ,m_pCurrSeqImPdu(0)
  26. ,m_pHearbeatTimer(0)
  27. ,m_pServerPingTimer(0)
  28. ,m_bDoReloginServerNow(FALSE)
  29. {
  30. m_pClientSocket = new TcpClientSocket;
  31. m_pClientSocket->registerCB(this);
  32. m_currSeqEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  33. m_eventConnected = CreateEvent(NULL, FALSE, FALSE, NULL);
  34. }
  35. // -----------------------------------------------------------------------------
  36. // TcpClientModule_Impl: Public, Destructor
  37. TcpClientModule_Impl::~TcpClientModule_Impl()
  38. {
  39. m_pClientSocket->unRegisterCB();
  40. delete m_pClientSocket;
  41. m_pClientSocket = 0;
  42. if (m_pCurrSeqImPdu)
  43. delete m_pCurrSeqImPdu;
  44. m_pCurrSeqImPdu = 0;
  45. CloseHandle(m_eventConnected);
  46. CloseHandle(m_currSeqEvent);
  47. }
  48. void TcpClientModule_Impl::release()
  49. {
  50. delete this;
  51. }
  52. void TcpClientModule_Impl::onClose(int error)
  53. {
  54. APP_LOG(LOG_ERROR, _T("TcpClientModule_Impl socket onClose(%d)"), error);
  55. m_tcpClientState = TCPCLIENT_STATE_DISCONNECT;
  56. GetLogic()->asynNotifyObserver(KEY_TCPCLIENT_STATE);
  57. _stopHearbeat();
  58. }
  59. void TcpClientModule_Impl::onReceiveData(const char* data, UInt32 size)
  60. {
  61. if (m_pServerPingTimer)
  62. m_pServerPingTimer->m_bHasReceivedPing = TRUE;
  63. PduHeader_t pduHead;
  64. CImPdu::ReadPduHeader((uchar_t*)data,(uint32_t)size, &pduHead);
  65. if (IM_PDU_TYPE_HEARTBEAT == pduHead.command_id && SID_OTHER == pduHead.module_id)
  66. {
  67. //模块器端过来的心跳包,不跳到业务层派发
  68. return;
  69. }
  70. if (g_seqNum == pduHead.reserved)
  71. {
  72. try
  73. {
  74. m_pCurrSeqImPdu = CImPdu::ReadPdu((uchar_t*)data, (uint32_t)size);
  75. }
  76. catch (CPduException e)
  77. {
  78. APP_LOG(LOG_ERROR, TRUE, _T("Logic_Impl onPacket CPduException serviceId:%d,commandId:%d,errCode:%d")
  79. , e.GetModuleId(), e.GetCommandId(), e.GetErrorCode());
  80. return;
  81. }
  82. catch (...)
  83. {
  84. APP_LOG(LOG_ERROR, TRUE, _T("Logic_Impl onPacket unknown exception"));
  85. return;
  86. }
  87. ::SetEvent(m_currSeqEvent);
  88. return;
  89. }
  90. //将网络包包装成任务放到逻辑任务队列里面去
  91. _handlePacketOperation(data, size);
  92. }
  93. void TcpClientModule_Impl::onParseError()
  94. {
  95. }
  96. void TcpClientModule_Impl::onConnectDone()
  97. {
  98. m_tcpClientState = TCPCLIENT_STATE_OK;
  99. ::SetEvent(m_eventConnected);
  100. m_bDoReloginServerNow = FALSE;
  101. if (!m_pServerPingTimer)
  102. {
  103. _startServerPingTimer();
  104. }
  105. }
  106. BOOL TcpClientModule_Impl::create()
  107. {
  108. return m_pClientSocket->create();
  109. }
  110. CImPdu* TcpClientModule_Impl::doLogin(CString &linkaddr, UInt16 port
  111. ,CString& uName,std::string& pass)
  112. {
  113. BOOL bRet = m_pClientSocket->connect(linkaddr, port);
  114. PTR_NULL(bRet);
  115. CImPduLoginResponse* pduLoginResp = 0;
  116. if (_waitConnectedNotify())
  117. {
  118. string name = util::cStringToString(uName);
  119. CImPduLoginRequest pduLogin(name.c_str(), pass.c_str(), USER_STATUS_ONLINE, CLIENT_TYPE_WINDOWS);
  120. pduLoginResp = (CImPduLoginResponse*)_sendPacketAndWaitResponse(&pduLogin);
  121. }
  122. return pduLoginResp;
  123. }
  124. void TcpClientModule_Impl::closeSocket()
  125. {
  126. m_pClientSocket->closeSocket();
  127. }
  128. void TcpClientModule_Impl::shutdown()
  129. {
  130. m_pClientSocket->shutdown();
  131. _stopHearbeat();
  132. _stopServerPingTimer();
  133. }
  134. CImPdu* TcpClientModule_Impl::_sendPacketAndWaitResponse(CImPdu* pdu, UInt32 timeout /*= 20*/)
  135. {
  136. if (TCPCLIENT_STATE_OK != m_tcpClientState)
  137. return 0;
  138. pdu->SetReserved(++g_seqNum);
  139. sendPacket(pdu);
  140. if (m_pCurrSeqImPdu)
  141. delete m_pCurrSeqImPdu;
  142. m_pCurrSeqImPdu = 0;
  143. UInt32 t = 0;
  144. timeout *= 1000;
  145. UInt32 waitResult;
  146. do
  147. {
  148. int timeWaiter = 500;
  149. t += timeWaiter;
  150. waitResult = WaitForSingleObject(m_currSeqEvent, timeWaiter);
  151. } while ((WAIT_TIMEOUT == waitResult) && (t < timeout));
  152. return m_pCurrSeqImPdu;
  153. }
  154. void TcpClientModule_Impl::sendPacket(CImPdu* pdu)
  155. {
  156. m_pClientSocket->send((const char*)pdu->GetBuffer(), pdu->GetLength());
  157. }
  158. BOOL TcpClientModule_Impl::_waitConnectedNotify()
  159. {
  160. int timeout = 10000; //10秒
  161. int t = 0;
  162. DWORD waitResult = WAIT_FAILED;
  163. do
  164. {
  165. int timeWaiter = 500;
  166. t += timeWaiter;
  167. waitResult = WaitForSingleObject(m_eventConnected, timeWaiter);
  168. } while ((WAIT_TIMEOUT == waitResult) && (t < timeout));
  169. return (WAIT_OBJECT_0 == waitResult);
  170. }
  171. void TcpClientModule_Impl::startHeartbeat()
  172. {
  173. GetLogic()->scheduleTimerWithLambda(5, TRUE,
  174. [=]()
  175. {
  176. GetLogic()->pushBackOperationWithLambda(
  177. [=]()
  178. {
  179. CImPduHeartbeat pduHeartbeat;
  180. sendPacket(&pduHeartbeat);
  181. }
  182. );
  183. }
  184. , &m_pHearbeatTimer);
  185. }
  186. void TcpClientModule_Impl::_stopHearbeat()
  187. {
  188. GetLogic()->killTimer(m_pHearbeatTimer);
  189. m_pHearbeatTimer = 0;
  190. }
  191. void TcpClientModule_Impl::_handlePacketOperation(const char* data, UInt32 size)
  192. {
  193. std::string copyInBuffer(data, size);
  194. GetLogic()->pushBackOperationWithLambda(
  195. [=]()
  196. {
  197. CImPdu* pPdu = 0;
  198. try
  199. {
  200. pPdu = CImPdu::ReadPdu((uchar_t*)copyInBuffer.data(), (uint32_t)copyInBuffer.size());
  201. }
  202. catch (CPduException e)
  203. {
  204. APP_LOG(LOG_ERROR, TRUE, _T("_handlePacketOperation CPduException moduleId:%d,commandId:%d,errCode:%d")
  205. , e.GetModuleId(), e.GetCommandId(), e.GetErrorCode());
  206. }
  207. catch (...)
  208. {
  209. APP_LOG(LOG_ERROR, TRUE, _T("_handlePacketOperation unknown exception"));
  210. }
  211. PTR_VOID(pPdu);
  212. IPduAsyncSocketModule* pModule
  213. = (IPduAsyncSocketModule*)GetLogic()->getModule(pPdu->GetModuleId());
  214. if (!pModule)
  215. {
  216. assert(FALSE);
  217. APP_LOG(LOG_ERROR, TRUE, _T("_handlePacketOperation module is null, moduleId:%d,commandId:%d")
  218. , pPdu->GetModuleId(), pPdu->GetCommandId());
  219. return;
  220. }
  221. std::auto_ptr<CImPdu> raiiImPdu(pPdu);
  222. pModule->onPacket(raiiImPdu);
  223. });
  224. }
  225. void TcpClientModule_Impl::_startServerPingTimer()
  226. {
  227. if (!m_pServerPingTimer)
  228. m_pServerPingTimer = new ServerPingTimer(this);
  229. logic::GetLogic()->scheduleTimer(m_pServerPingTimer, 60, TRUE);
  230. }
  231. void TcpClientModule_Impl::_stopServerPingTimer()
  232. {
  233. if (m_pServerPingTimer)
  234. logic::GetLogic()->killTimer(m_pServerPingTimer);
  235. m_pServerPingTimer = 0;
  236. }
  237. void TcpClientModule_Impl::_doReloginServer()
  238. {
  239. APP_LOG(LOG_INFO, TRUE, _T("doReloginServer now!!!"));
  240. m_bDoReloginServerNow = TRUE;
  241. onClose(0);
  242. }
  243. UInt8 TcpClientModule_Impl::getTcpClientNetState() const
  244. {
  245. return m_tcpClientState;
  246. }
  247. ServerPingTimer::ServerPingTimer(TcpClientModule_Impl* pTcpClient)
  248. :m_pTcpClient(pTcpClient)
  249. ,m_bHasReceivedPing(FALSE)
  250. {
  251. }
  252. void ServerPingTimer::process()
  253. {
  254. if (!m_bHasReceivedPing && !m_pTcpClient->m_bDoReloginServerNow)
  255. {
  256. m_pTcpClient->_doReloginServer();
  257. }
  258. m_bHasReceivedPing = FALSE;
  259. }
  260. void ServerPingTimer::release()
  261. {
  262. delete this;
  263. }
  264. NAMESPACE_END(logic)
  265. /******************************************************************************/