📄 network.cpp
字号:
/******************************************************************************** network.cpp:*-------------------------------------------------------------------------------* (c)1999-2001 VideoLAN* $Id: network.cpp,v 1.5 2002/06/19 22:53:51 massiot Exp $** Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**-------------------------------------------------------------------------------********************************************************************************//******************************************************************************** C_ConnectionsHandler class********************************************************************************* *******************************************************************************///------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------// //------------------------------------------------------------------------------template <class Session> C_ConnectionsHandler<Session>::C_ConnectionsHandler(handle hLog, void* pParam) : m_cSessions(7){ ASSERT(hLog); ASSERT(pParam); m_hLog = hLog; m_pParam = pParam; m_bContinue = true; // Create the server socket m_pServerSocket = new C_Socket(); ASSERT(m_pServerSocket);}//------------------------------------------------------------------------------// Destructor//------------------------------------------------------------------------------////------------------------------------------------------------------------------template <class Session> C_ConnectionsHandler<Session>::~C_ConnectionsHandler(){ delete m_pServerSocket;}//------------------------------------------------------------------------------// Initialization//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::Init(int iDomain, const C_String& strAddr, const C_String& strPort){ ASSERT(m_pServerSocket); // Initialize the socket that will wait for the client connections m_pServerSocket->Open(iDomain, SOCK_STREAM, 0);#ifndef _WIN32 int iOptVal = 1; m_pServerSocket->SetOption(SOL_SOCKET, SO_REUSEADDR, (char *)&iOptVal, sizeof(iOptVal));#endif m_pServerSocket->Bind(strAddr, strPort); m_pServerSocket->Listen(5); m_cActiveSockets.AddRecv(m_pServerSocket);}//------------------------------------------------------------------------------// Execution//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::Run(){ while(m_bContinue) { try { // Monitor the active sockets with a timeout of 1 second C_Socket* pSocket = m_cActiveSockets.Monitor(1); if(pSocket == m_pServerSocket) { // A new client is trying to connect EstablishConnection(pSocket); } else if(pSocket != NULL) { // A client has sent some data ProcessConnection(pSocket); } } catch(E_Exception e) { // This should not be a fatal error, so don't break the loop Log(m_hLog, LOG_ERROR, "Ignoring unexpected error: " + e.Dump()); } }}//------------------------------------------------------------------------------// Stop the telnet main loop: the telnet will automaticly die//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::Stop(){ m_bContinue = false; // We should find a way to synchronise ourself with the monitor timeout to // be completly clean // Why ? I don't see any possible race condition. Benny}//------------------------------------------------------------------------------// Destruction//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::Destroy(){ Log(m_hLog, LOG_NOTE, "Shutdowning all the opened sessions..."); // Close all opened session C_HashTableIterator<handle, Session> cIterator = m_cSessions.CreateIterator(); while(cIterator.HasNext()) { C_HashTableNode<handle, Session>* pNode = cIterator.GetNext(); C_Socket* pConnection = (C_Socket*)pNode->GetKey(); CloseConnection(pConnection); cIterator.Reset(); } // Close server socket m_cActiveSockets.RemoveRecv(*m_pServerSocket); m_pServerSocket->Close();}//------------------------------------------------------------------------------// Establish a connection with a client//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::EstablishConnection(C_Socket* pServerSocket){ C_Socket* pClientSocket = pServerSocket->Accept(); ASSERT(pClientSocket); C_String strPeerName; try { strPeerName = pClientSocket->GetPeerName(); } catch(E_Exception e) { strPeerName = "Unknown"; } // Begin the connection Log(m_hLog, LOG_NOTE, "Processing incoming connection from " + strPeerName); m_cActiveSockets.AddRecv(pClientSocket); Session* pSession = new Session(pClientSocket, m_pParam); pSession->m_strPeerName = strPeerName; pSession->Init(); m_cSessions.Add(pClientSocket, pSession);}//------------------------------------------------------------------------------// Close the connection with a client//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::CloseConnection(C_Socket* pClientSocket){ ASSERT(pClientSocket); m_cActiveSockets.RemoveRecv(*pClientSocket); Session* pSession = m_cSessions.Remove(pClientSocket); ASSERT(pSession); try { Log(m_hLog, LOG_NOTE, "Closing connection from "+pSession->m_strPeerName); pSession->Close(); delete pSession; } catch(E_Exception e) { Log(m_hLog, LOG_ERROR, "Connection from " + pSession->m_strPeerName + " could not be closed: " + e.Dump()); }}//------------------------------------------------------------------------------// Handle the data received on a connection//------------------------------------------------------------------------------template <class Session> void C_ConnectionsHandler<Session>::ProcessConnection(C_Socket* pClientSocket){ Session* pSession = m_cSessions.Get(pClientSocket); ASSERT(pSession); try { pSession->ProcessData(); } catch(E_Exception e) { Log(m_hLog, LOG_WARN, "Error when processing data from " + pSession->m_strPeerName + ": closing connection" + "(error was: " + e.Dump() +")"); CloseConnection(pClientSocket); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -