#include "StdAfx.h" #include "ClientContainer.h" #include "NetClient.h" CClientContainer::CClientContainer(void) { } CClientContainer::~CClientContainer(void) { release(); } /***************************************************************** **【函数名称】 __add2List **【函数功能】 客户端添加到指定队列中 **【参数】 **【返回值】 ****************************************************************/ void CClientContainer::__add2List( CNetClient* a_pClient, ListClient& a_list, CCriticalSection* a_pCs ) { CSingleLock Lock(a_pCs); Lock.Lock(); a_list.AddTail(a_pClient); } /***************************************************************** **【函数名称】 __onConnFailedProc **【函数功能】 客户端连接断开/失败的后续处理 **【参数】 a_pClient: 连接断开/失败的客户端 **【返回值】 ****************************************************************/ void CClientContainer::__onConnFailedProc( CNetClient* a_pClient ) { // 连接类型处理不同 if(a_pClient->linkType() == PDU_LINK_TYPE_CLIENT) { __add2List(a_pClient, m_listConnecting, &m_CS4Connecting); } else { __deleteClient(a_pClient); } // end if } /***************************************************************** **【函数名称】 __deleteClient **【函数功能】 删除指定的连接 **【参数】 **【返回值】 ****************************************************************/ void CClientContainer::__deleteClient( CNetClient* a_pClient ) { ASSERT(a_pClient != NULL); a_pClient->drop(); __add2List(a_pClient, m_ListDeleted, &m_Cs4Deleted); } /***************************************************************** **【函数名称】 __removeClient **【函数功能】 从LIST中移出指定的连接(不是删除) **【参数】 **【返回值】 ****************************************************************/ bool CClientContainer::__removeClient( CNetClient* a_pClient, ListClient& a_list, CCriticalSection* a_pCs ) { ASSERT(a_pClient != NULL); CSingleLock Locker(a_pCs); Locker.Lock(); POSITION Pos = a_list.Find(a_pClient); if(Pos != NULL) { a_list.RemoveAt(Pos); return true; } else return false; } /***************************************************************** **【函数名称】 __lookup **【函数功能】 从LIST中查找指定的连接 **【参数】 a_nFarType 对端设备类型 a_nFarId 对端设备ID **【返回值】 ****************************************************************/ CNetClient* CClientContainer::__lookup( PDU_DEV_TYPE a_nFarType, int a_nFarId, ListClient& a_list, CCriticalSection* a_pCs ) { CSingleLock Locker(a_pCs); Locker.Lock(); POSITION pos = a_list.GetHeadPosition(); PDU_DEV_TYPE nType = PDU_DEV_TYPE_UNKNOWN; int nId = -1; while(pos != NULL) { CNetClient* pClient = a_list.GetNext(pos); ASSERT(pClient != NULL); pClient->getFarDevInfo(nType, nId); if(nType == a_nFarType && nId == a_nFarId) return pClient; } // end while return NULL; } /***************************************************************** **【函数名称】 __lookup **【函数功能】 从LIST中查找指定的连接 **【参数】 a_hSocket SOCKET句柄 **【返回值】 ****************************************************************/ CNetClient* CClientContainer::__lookup( SOCKET a_hSocket, ListClient& a_list, CCriticalSection* a_pCs ) { CSingleLock Locker(a_pCs); Locker.Lock(); POSITION pos = a_list.GetHeadPosition(); while(pos != NULL) { CNetClient* pClient = a_list.GetNext(pos); ASSERT(pClient != NULL); if(pClient->assoSocket() == a_hSocket) return pClient; } // end while return NULL; } /***************************************************************** **【函数名称】 __lookup **【函数功能】 从LIST中查找指定的连接 **【参数】 **【返回值】 ****************************************************************/ CNetClient* CClientContainer::__lookup( CNetClient* a_pClient, ListClient& a_list, CCriticalSection* a_pCs ) { CSingleLock Locker(a_pCs); Locker.Lock(); POSITION Pos = a_list.Find(a_pClient); if(Pos != NULL) return a_pClient; else return NULL; } /***************************************************************** **【函数名称】 __lookup4Delete **【函数功能】 从LIST中查找指定的连接并删除 **【参数】 **【返回值】 ****************************************************************/ bool CClientContainer::__lookup4Delete( PDU_DEV_TYPE a_nFarType, int a_nFarId, ListClient& a_list, CCriticalSection* a_pCs ) { CSingleLock Locker(a_pCs); Locker.Lock(); PDU_DEV_TYPE nType = PDU_DEV_TYPE_UNKNOWN; int nId = -1; POSITION pos = a_list.GetHeadPosition(); while(pos != NULL) { POSITION posPrev = pos; CNetClient* pClient = a_list.GetNext(pos); ASSERT(pClient != NULL); pClient->getFarDevInfo(nType, nId); if(nType == a_nFarType && nId == a_nFarId) { a_list.RemoveAt(posPrev); // 删除 __deleteClient(pClient); return true; } } // end while return false; } /***************************************************************** **【函数名称】 __lookup4Delete **【函数功能】 从LIST中查找指定的连接并删除 **【参数】 **【返回值】 ****************************************************************/ bool CClientContainer::__lookup4Delete( SOCKET a_hSocket, ListClient& a_list, CCriticalSection* a_pCs ) { CSingleLock Locker(a_pCs); Locker.Lock(); POSITION pos = a_list.GetHeadPosition(); while(pos != NULL) { POSITION posPrev = pos; CNetClient* pClient = a_list.GetNext(pos); ASSERT(pClient != NULL); if(pClient->assoSocket() == a_hSocket) { a_list.RemoveAt(posPrev); // 删除 __deleteClient(pClient);; return true; } } // end while return false; } /***************************************************************** **【函数名称】 insertSocket **【函数功能】 添加一个新的连接 **【参数】 a_pSocket 要添加的连接 **【返回值】 ****************************************************************/ void CClientContainer::insertClient( CNetClient* a_pClient ) { __add2List(a_pClient, m_listConnecting, &m_CS4Connecting); } /***************************************************************** **【函数名称】 removeClient **【函数功能】 删除一个连接 **【参数】 **【返回值】 ****************************************************************/ bool CClientContainer::removeClient( PDU_DEV_TYPE a_nFarType, int a_nFarId ) { // 注意此处的查找顺序:会影响到座席的重复签入控制 // 已注册的客户端 if(__lookup4Delete(a_nFarType, a_nFarId, m_listRegisted, &m_CS4Registed)) return true; // 已连接的客户端 if(__lookup4Delete(a_nFarType, a_nFarId, m_listConnected, &m_CS4Connected)) return true; // 正在连接的客户端 if(__lookup4Delete(a_nFarType, a_nFarId, m_listConnecting, &m_CS4Connecting)) return true; return false; } /***************************************************************** **【函数名称】 removeClient **【函数功能】 删除一个连接 **【参数】 **【返回值】 ****************************************************************/ bool CClientContainer::removeClient( SOCKET a_hSocket ) { // 已注册的客户端 if(__lookup4Delete(a_hSocket, m_listRegisted, &m_CS4Registed)) return true; // 已连接的客户端 if(__lookup4Delete(a_hSocket, m_listConnected, &m_CS4Connected)) return true; // 正在连接的客户端 if(__lookup4Delete(a_hSocket, m_listConnecting, &m_CS4Connecting)) return true; return false; } /***************************************************************** **【函数名称】 getClient **【函数功能】 根据对端设备类型、ID查找指定连接 **【参数】 a_nFarType 对端设备类型 a_nFarId 对端设备ID **【返回值】 ****************************************************************/ CNetClient* CClientContainer::getClient( PDU_DEV_TYPE a_nFarType, int a_nFarId ) { // 已注册的SOCKET CNetClient* pCLient = __lookup(a_nFarType, a_nFarId, m_listRegisted, &m_CS4Registed); if(pCLient != NULL) return pCLient; // 已连接的SOCKET pCLient = __lookup(a_nFarType, a_nFarId, m_listConnected, &m_CS4Connected); if(pCLient != NULL) return pCLient; // 正在连接的SOCKET pCLient = __lookup(a_nFarType, a_nFarId, m_listConnecting, &m_CS4Connecting); if(pCLient != NULL) return pCLient; return NULL; } /***************************************************************** **【函数名称】 getClient **【函数功能】 根据SOCKET句柄查找指定连接 **【参数】 a_hSocket SOCKET句柄 **【返回值】 ****************************************************************/ CNetClient* CClientContainer::getClient( SOCKET a_hSocket ) { CNetClient* pClient = NULL; pClient = __lookup(a_hSocket, m_listConnecting, &m_CS4Connecting); if(pClient != NULL) return pClient; pClient = __lookup(a_hSocket, m_listConnected, &m_CS4Connected); if(pClient != NULL) return pClient; pClient = __lookup(a_hSocket, m_listRegisted, &m_CS4Registed); if(pClient != NULL) return pClient; return NULL; } /***************************************************************** **【函数名称】 getClient **【函数功能】 根据SOCKET句柄查找指定连接 **【参数】 **【返回值】 ****************************************************************/ CNetClient* CClientContainer::getClient( CNetClient* a_pClient ) { CNetClient* pClient = NULL; pClient = __lookup(a_pClient, m_listRegisted, &m_CS4Registed); if(pClient != NULL) return pClient; pClient = __lookup(a_pClient, m_listConnecting, &m_CS4Connecting); if(pClient != NULL) return pClient; pClient = __lookup(a_pClient, m_listConnected, &m_CS4Connected); if(pClient != NULL) return pClient; return NULL; } /***************************************************************** **【函数名称】 send2All **【函数功能】 向所有注册过的客户端发送PDU **【参数】 **【返回值】 ****************************************************************/ void CClientContainer::send2All( CPduEntity* a_pPdu ) { ASSERT(a_pPdu != NULL); CSingleLock Locker(&m_CS4Registed); Locker.Lock(); POSITION pos = m_listRegisted.GetHeadPosition(); while(pos != NULL) { CNetClient* pClient = m_listRegisted.GetNext(pos); ASSERT(pClient != NULL); pClient->sendPdu(a_pPdu); } // end while } /***************************************************************** **【函数名称】 release **【函数功能】 释放资源 **【参数】 **【返回值】 ****************************************************************/ void CClientContainer::release( void ) { while(m_ListDeleted.GetCount() > 0) { delete m_ListDeleted.RemoveHead(); } while(m_listConnecting.GetCount() > 0) { delete m_listConnecting.RemoveHead(); } while(m_listConnected.GetCount() > 0) { delete m_listConnected.RemoveHead(); } while(m_listRegisted.GetCount() > 0) { delete m_listRegisted.RemoveHead(); } } /***************************************************************** **【函数名称】 clearClientDeleted **【函数功能】 清理缓存的已删除客户端 **【参数】 **【返回值】 ****************************************************************/ void CClientContainer::clearClientDeleted( void ) { m_Cs4Deleted.Lock(); while(m_ListDeleted.GetCount() > 0) delete m_ListDeleted.RemoveHead(); m_Cs4Deleted.Unlock(); } /***************************************************************** **【函数名称】 onConnEstablished **【函数功能】 连接建立事件处理 **【参数】 a_pClient 已建立连接的客户端 **【返回值】 ****************************************************************/ PDU_LINK_STATE CClientContainer::onConnEstablished( CNetClient* a_pClient ) { PDU_LINK_STATE nLinkState = PDU_LINK_STATE_UNKNOWN; // 未知 if(a_pClient->linkType() == PDU_LINK_TYPE_SERVER) // SERVER端 { __add2List(a_pClient, m_listConnected, &m_CS4Connected); nLinkState = PDU_LINK_STATE_ACCEPTED; } else // CLIENT端 { __removeClient(a_pClient, m_listConnecting, &m_CS4Connecting); __add2List(a_pClient, m_listConnected, &m_CS4Connected); nLinkState = PDU_LINK_STATE_SUCCESSED; } // end if return nLinkState; } /***************************************************************** **【函数名称】 onConnFailed **【函数功能】 连接失败/断开事件处理 **【参数】 a_pClient 已建立连接的客户端 **【返回值】 ****************************************************************/ PDU_LINK_STATE CClientContainer::onConnFailed( CNetClient* a_pClient ) { PDU_LINK_STATE nLinkState = PDU_LINK_STATE_UNKNOWN; // 未知 if(__removeClient(a_pClient, m_listRegisted, &m_CS4Registed)) // 正在进行通讯 { nLinkState = PDU_LINK_STATE_DISCONNECTED; __onConnFailedProc(a_pClient); // 后续处理 } else if(__removeClient(a_pClient, m_listConnected, &m_CS4Connected)) // 未握手 { nLinkState = PDU_LINK_STATE_DISCONNECTED; __onConnFailedProc(a_pClient); // 后续处理 } else if(__lookup(a_pClient->assoSocket(), m_listConnecting, &m_CS4Connecting) != NULL) // 初次连接/重连 { nLinkState = PDU_LINK_STATE_FAILED; } else { nLinkState = PDU_LINK_STATE_FAILED; } // end if return nLinkState; } /***************************************************************** **【函数名称】 onConnRegistOK **【函数功能】 连接注册成功事件处理 **【参数】 a_pClient 已注册成功的客户端 **【返回值】 ****************************************************************/ PDU_LINK_STATE CClientContainer::onConnRegistOK( CNetClient* a_pClient ) { __removeClient(a_pClient, m_listConnected, &m_CS4Connected); __add2List(a_pClient, m_listRegisted, &m_CS4Registed); return PDU_LINK_STATE_REG_OK; } /***************************************************************** **【函数名称】 onConnRegistFailed **【函数功能】 连接注册失败事件处理 **【参数】 a_pClient 已注册失败的客户端 **【返回值】 ****************************************************************/ PDU_LINK_STATE CClientContainer::onConnRegistFailed( CNetClient* a_pClient ) { return PDU_LINK_STATE_REG_FAILED; }