NetServer.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:6k
源码类别:

模拟服务器

开发平台:

C/C++

  1. // NetServer.cpp: implementation of the CNetServer class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Global.h"
  6. #include "NetServer.h"
  7. #include "S3Relay.h"
  8. //////////////////////////////////////////////////////////////////////
  9. // Construction/Destruction
  10. //////////////////////////////////////////////////////////////////////
  11. CNetServer::CNetServer()
  12. : m_pServer(NULL), m_ready(FALSE)
  13. {
  14. }
  15. CNetServer::~CNetServer()
  16. {
  17. //assert(!m_pServer);
  18. //_SafeRelease(m_pServer);
  19. }
  20. //static 
  21. void __stdcall CNetServer::ServerEventNotify(
  22. LPVOID lpParam,
  23. const unsigned long &ulnID,
  24. const unsigned long &ulnEventType )
  25. {
  26. CNetServer* pThis = (CNetServer*)lpParam;
  27. assert(pThis);
  28. switch( ulnEventType )
  29. {
  30. case enumClientConnectCreate:
  31. pThis->_NotifyClientConnectCreate(ulnID);
  32. break;
  33. case enumClientConnectClose:
  34. pThis->_NotifyClientConnectClose(ulnID);
  35. break;
  36. }
  37. }
  38. BOOL CNetServer::Startup (size_t nPlayerMaxCount, size_t nPrecision, size_t maxFreeBuffers_Cache, size_t bufferSize_Cache,
  39.   unsigned long ulnAddressToListenOn, unsigned short usnPortToListenOn)
  40. {
  41. if (m_pServer)
  42. return FALSE;
  43. AUTOLOCKWRITE(m_lockAccess);
  44. assert(!m_ready);
  45. m_ready = FALSE;
  46. assert(m_mapId2Connect.empty());
  47. m_mapId2Connect.clear();
  48. IServerFactory* pSvrFac = NULL;
  49. if (FAILED(g_libHeaven.CreateInterface( IID_IServerFactory, reinterpret_cast< void ** >(&pSvrFac) )))
  50. return FALSE;
  51. pSvrFac->SetEnvironment(nPlayerMaxCount, nPrecision, maxFreeBuffers_Cache, bufferSize_Cache);
  52. pSvrFac->CreateServerInterface(IID_IIOCPServer, reinterpret_cast< void ** >(&m_pServer));
  53. pSvrFac->Release();
  54. //init server
  55. if (FAILED(m_pServer->Startup()))
  56. return FALSE;
  57. m_pServer->RegisterMsgFilter((LPVOID)this, ServerEventNotify);
  58. OnBuildup();
  59. m_pServer->OpenService(ulnAddressToListenOn, usnPortToListenOn);
  60. m_ready = TRUE;
  61. return TRUE;
  62. }
  63. BOOL CNetServer::Shutdown()
  64. {
  65. AUTOLOCKWRITE(m_lockAccess);
  66. m_ready = FALSE;
  67. if (m_pServer)
  68. {
  69. m_pServer->CloseService();
  70. OnClearup();
  71. {{
  72. for (ID2CONNECTMAP::iterator it = m_mapId2Connect.begin(); it != m_mapId2Connect.end(); it++)
  73. {
  74. m_pServer->ShutdownClient((*it).first);
  75. CNetConnect* pConn = (*it).second;
  76. assert(pConn);
  77. if (pConn)
  78. {
  79. #ifndef _WORKMODE_SINGLETHREAD
  80. pConn->Stop();
  81. DestroyConnect(pConn);
  82. #endif
  83. }
  84. }
  85. m_mapId2Connect.clear();
  86. }}
  87. m_pServer->Cleanup();
  88. m_pServer->Release();
  89. m_pServer = NULL;
  90. }
  91. return TRUE;
  92. }
  93. BOOL CNetServer::Disconnect(unsigned long id)
  94. {
  95. if (!m_pServer)
  96. return FALSE;
  97. //the event will be do clearing !
  98. return SUCCEEDED(m_pServer->ShutdownClient(id));
  99. }
  100. void CNetServer::_NotifyClientConnectCreate(unsigned long ulnID)
  101. {
  102. AUTOLOCKWRITE(m_lockAccess);
  103. assert(m_pServer);
  104. assert(m_mapId2Connect.find(ulnID) == m_mapId2Connect.end());
  105. BOOL oncreate = FALSE;
  106. ID2CONNECTMAP::iterator itID = m_mapId2Connect.end();
  107. CNetConnect* pConn = CreateConnect(this, ulnID);
  108. if (pConn == NULL)
  109. goto on_fail;
  110. #ifdef _WORKMODE_MULTITHREAD2
  111. m_pServer->RegisterMsgFilter(ulnID, pConn);
  112. #endif
  113. OnClientConnectCreate(pConn);
  114. pConn->_NotifyClientConnectCreate();
  115. oncreate = TRUE;
  116. {{
  117. std::pair<ID2CONNECTMAP::iterator, bool> insret = m_mapId2Connect.insert(ID2CONNECTMAP::value_type(ulnID, pConn));
  118. itID = insret.first;
  119. if (!insret.second) //has existed ? unexpected
  120. {
  121. rTRACE("warning: unexpected repeated connect");
  122. CNetConnect* pConnOld = (*itID).second;
  123. if (pConnOld)
  124. {
  125. try
  126. {
  127. #ifndef _WORKMODE_SINGLETHREAD
  128. pConnOld->Stop();
  129. #endif
  130. pConnOld->_NotifyClientConnectClose();
  131. DestroyConnect(pConnOld);
  132. }
  133. catch (...)
  134. {
  135. assert(FALSE);
  136. }
  137. }
  138. (*itID).second = pConn;
  139. }
  140. }}
  141. #ifndef _WORKMODE_SINGLETHREAD
  142. if (!pConn->Start())
  143. goto on_fail;
  144. #endif
  145. return; //succ
  146. on_fail:
  147. rTRACE("error: connect initial fail");
  148. try
  149. {
  150. if (oncreate)
  151. {
  152. OnClientConnectClose(pConn);
  153. pConn->_NotifyClientConnectClose();
  154. }
  155. m_pServer->ShutdownClient(ulnID);
  156. if (pConn != NULL)
  157. DestroyConnect(pConn);
  158. if (itID != m_mapId2Connect.end())
  159. m_mapId2Connect.erase(itID);
  160. }
  161. catch (...)
  162. {
  163. assert(FALSE);
  164. }
  165. }
  166. void CNetServer::_NotifyClientConnectClose(unsigned long ulnID)
  167. {
  168. AUTOLOCKWRITE(m_lockAccess);
  169. ID2CONNECTMAP::iterator it = m_mapId2Connect.find(ulnID);
  170. if (it != m_mapId2Connect.end())
  171. {
  172. CNetConnect* pConn = (*it).second;
  173. assert(pConn);
  174. if (pConn)
  175. {
  176. pConn->Stop();
  177. pConn->_NotifyClientConnectClose();
  178. OnClientConnectClose(pConn);
  179. }
  180. m_mapId2Connect.erase(it);
  181. DestroyConnect(pConn);
  182. }
  183. }
  184. size_t CNetServer::GetConnectCount() 
  185. {
  186. AUTOLOCKREAD(m_lockAccess);
  187. return m_mapId2Connect.size();
  188. }
  189. BOOL CNetServer::IsConnectReady(unsigned long id)
  190. {
  191. AUTOLOCKREAD(m_lockAccess);
  192. return m_mapId2Connect.find(id) != m_mapId2Connect.end();
  193. }
  194. CNetConnectDup CNetServer::FindNetConnect(unsigned long id)
  195. {
  196. AUTOLOCKREAD(m_lockAccess);
  197. ID2CONNECTMAP::iterator it = m_mapId2Connect.find(id);
  198. if (it == m_mapId2Connect.end())
  199. return CNetConnectDup();
  200. CNetConnect* pNetConn = (*it).second;
  201. if (pNetConn == NULL)
  202. return CNetConnectDup();
  203. return CNetConnectDup(*pNetConn);
  204. }
  205. BOOL CNetServer::BroadPackage(const void* pData, size_t size)
  206. {
  207. if (!m_ready || m_pServer == NULL)
  208. return FALSE;
  209. AUTOLOCKREAD(m_lockAccess);
  210. for (ID2CONNECTMAP::iterator it = m_mapId2Connect.begin(); it != m_mapId2Connect.end(); it++)
  211. {
  212. CNetConnect* pNetConnect = (*it).second;
  213. assert(pNetConnect);
  214. if (pNetConnect)
  215. pNetConnect->SendPackage(pData, size);
  216. }
  217. return TRUE;
  218. }
  219. BOOL CNetServer::Route()
  220. {
  221. AUTOLOCKREAD(m_lockAccess);
  222. if (m_pServer == NULL)
  223. return FALSE;
  224. for (ID2CONNECTMAP::iterator it = m_mapId2Connect.begin(); it != m_mapId2Connect.end(); it++)
  225. {
  226. CNetConnect* pConnect = (*it).second;
  227. assert(pConnect);
  228. if (pConnect != NULL)
  229. pConnect->Route();
  230. }
  231. return TRUE;
  232. }