/****************************************************************/ /* */ /* CONNECTTHREAD.CPP */ /* */ /* Implementation of the Connect Thread. */ /* Created when a client logs on to the server and processes */ /* 'Send' commando's. */ /* */ /* Programmed by LYFZ van der Meer */ /* http://www.LYFZvandermeer.nl */ /* */ /* Last updated: 15 july 2002 */ /* */ /****************************************************************/ //在ConnectThread.cpp文件中实现连接线程的创建,这个线程用来处理与客户端的连接。 //当一个客户登录到服务器此线程将被创建,并处理"Send"命令。 #include "stdafx.h" #include "DBServer.h" #include "theDBServer.h" #include "DBServerDlg.h" #include "ConnectThread.h" #include "MyLock.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif extern CtheDBServer *g_pWndServer; CStringArray g_connuserarray; CStringArray g_logintimearray; extern CConnectThread *g_pThreadPt[200]; extern int g_conncount; IMPLEMENT_DYNCREATE(CConnectThread, CWinThread) /********************************************************************/ /* */ /* Function name : CConnectThread::CConnectThread */ /* Description : Constructor */ /* */ /********************************************************************/ CConnectThread::CConnectThread() { m_nReceivedBytes = 0; m_nSentBytes = 0; m_nTimerID = 0; m_LastDataTransferTime = CTime::GetCurrentTime(); } /********************************************************************/ /* */ /* Function name : CConnectThread::~CConnectThread */ /* Description : Destructor */ /* */ /********************************************************************/ CConnectThread::~CConnectThread() { } /********************************************************************/ /* */ /* Function name : InitInstance */ /* Description : Perform tasks that must be completed when the */ /* thread is first created. */ /* */ /********************************************************************/ //初始化线程 int FindArray3(CStringArray *pArray, CString Str) { int count=0; for(int i=0; iGetSize (); i++) { if(pArray->ElementAt (i)==Str) count++; } return count; } extern void GetOneConn(CDatabase **m_pdb, CArray*m_dbarray, CConnectThread *pThread); extern int FindArray(CStringArray *pArray, CString Str); void GetConnCount(CStringArray *pArray) { g_pWndServer->m_CriticalSection.Lock(); CConnectThread *pThread; POSITION pos; pos=g_pWndServer->m_ThreadList.GetHeadPosition(); while(pos) { pThread=g_pWndServer->m_ThreadList.GetNext(pos); if(g_localip==pThread->m_strRemoteHost)continue; if(::FindArray(pArray, pThread->m_strRemoteHost)==-1) pArray->Add(pThread->m_strRemoteHost); } g_pWndServer->m_CriticalSection.Unlock(); } BOOL CConnectThread::InitInstance() { try { g_pWndServer->m_CriticalSection.Lock(); g_pWndServer->m_ThreadList.AddTail(this); g_pWndServer->m_CriticalSection.Unlock(); m_ConnectSocket.Attach(m_hSocket); m_ConnectSocket.Init(); m_ConnectSocket.m_pThread = this; CString strIPAddress; UINT nPort; m_ConnectSocket.GetPeerName(strIPAddress, nPort); m_strRemoteHost=strIPAddress; m_strRemoteHost.TrimLeft (); #ifdef CONNCOUNT_VERSION if(g_localip!=strIPAddress) { CStringArray iparray; BOOL bmax=0; if(1) { // GetConnCount(&iparray); if(FindArray3(&g_connuserarray, strIPAddress)==0 && g_connuserarray.GetSize ()>g_conncount) // if( iparray.GetSize ()>g_conncount) { bmax=1; } } if(bmax) { CString ss; // ss.Format("座席版连接超数。ip:%s被拒绝。%d/%d", strIPAddress, iparray.GetSize (), g_conncount); ss.Format("座席版连接超数。ip:%s被拒绝。%d/%d", strIPAddress, g_connuserarray.GetSize (), g_conncount); WriteTextLog(ss); PostThreadMessage(WM_QUIT,0,0); return 0; } else if(FindArray3(&g_connuserarray, strIPAddress)==0) { MyLock lock("g_connuserarray"); g_connuserarray.Add (strIPAddress); g_logintimearray.Add (CTime::GetCurrentTime ().Format("%H:%M:%S")); } } #endif // 通知服务器一个新的连接到达 g_pWndServer->SendMessage(WM_THREADSTART, (WPARAM)this, 0); /* if(AddConn(&m_conndb, "db")==0) { WriteTextLog("打开新数据库连接失败"); PostThreadMessage(WM_QUIT,0,0); return 0; } m_conndb.SetQueryTimeout(60*2); m_ConnectSocket.m_pConndb=&m_conndb;*/ //获取数据库连接 m_ConnectSocket.m_pdb=NULL; #if USE_ADO_OPT_DB m_ConnectSocket.m_pAdoImpl = NULL; GetOneConn(&m_ConnectSocket.m_pdb, &m_ConnectSocket.m_pAdoImpl, &m_ConnectSocket.m_dbarray, this); #else GetOneConn(&m_ConnectSocket.m_pdb, &m_ConnectSocket.m_dbarray, this); #endif//#if USE_ADO_OPT_DB /* if (g_pWndServer->CheckMaxUsers()) { // m_ConnectSocket.SendResponse("421 Too many users are connected, please try again later."); WriteTextLog("连接超过最大许可");PostThreadMessage(WM_QUIT,0,0); } else if (!g_pWndServer->IsIPAddressAllowed(strIPAddress)) { // m_ConnectSocket.SendResponse("421 Access denied, IP address was rejected by the server."); WriteTextLog("非法IP地址"); PostThreadMessage(WM_QUIT,0,0); } else*/ { // AfxMessageBox(strIPAddress); // 发送欢迎信息给客户端 // m_ConnectSocket.SendResponse("220 %s", g_pWndServer->GetWelcomeMessage()); m_nTimerID = ::SetTimer(NULL, 0, 1000, TimerProc); } } catch(CException *e) { e->Delete(); } return TRUE; } /********************************************************************/ /* */ /* Function name : ExitInstance */ /* Description : Perform clean-up when the thread terminates. */ /* */ /********************************************************************/ //线程终止 extern int FindArray(CStringArray *pArray, CString Str); int CConnectThread::ExitInstance() { try { g_pWndServer->m_CriticalSection.Lock(); // 从链表中删除当前线程 POSITION pos = g_pWndServer->m_ThreadList.Find(this); if(pos != NULL) { g_pWndServer->m_ThreadList.RemoveAt(pos); } g_pWndServer->m_CriticalSection.Unlock(); //通知服务主循环 g_pWndServer->SendMessage(WM_THREADCLOSE, (WPARAM)this, 0); /* #ifdef CONNCOUNT_VERSION MyLock lock("g_connuserarray"); int pos2=::FindArray (&g_connuserarray, m_strRemoteHost); if(pos2!=-1) g_connuserarray.RemoveAt (pos2); #endif */ for(int i=0; i<200; i++) { if(g_pThreadPt[i]==this) { g_pThreadPt[i]=NULL; //WriteTextLog("线程退出"); return CWinThread::ExitInstance(); } } } catch(CException *e) { g_pWndServer->m_CriticalSection.Unlock(); e->Delete(); } return CWinThread::ExitInstance(); } BEGIN_MESSAGE_MAP(CConnectThread, CWinThread) //{{AFX_MSG_MAP(CConnectThread) //}}AFX_MSG_MAP //ON_MESSAGE(WM_THREADMSG, OnThreadMessage) ON_THREAD_MESSAGE(WM_THREADMSG, OnThreadMessage) END_MESSAGE_MAP() /********************************************************************/ /* */ /* Function name : IncSentBytes */ /* Description : Increment number of bytes sent by the server. */ /* */ /********************************************************************/ void CConnectThread::IncSentBytes(int nBytes) { m_LastDataTransferTime = CTime::GetCurrentTime(); m_nSentBytes += nBytes; // notify server class g_pWndServer->PostMessage(WM_THREADMSG, (WPARAM)0, (LPARAM)nBytes); } /********************************************************************/ /* */ /* Function name : IncReceivedBytes */ /* Description : Increment number of bytes received by the server.*/ /* */ /********************************************************************/ void CConnectThread::IncReceivedBytes(int nBytes) { m_LastDataTransferTime = CTime::GetCurrentTime(); m_nReceivedBytes += nBytes; // notify server class g_pWndServer->PostMessage(WM_THREADMSG, (WPARAM)1, (LPARAM)nBytes); } /********************************************************************/ /* */ /* Function name : UpdateStatistic */ /* Description : Specific statistics has been changed. */ /* */ /********************************************************************/ void CConnectThread::UpdateStatistic(int nType) { // notify server class g_pWndServer->PostMessage(WM_THREADMSG, (WPARAM)2, (LPARAM)nType); } /********************************************************************/ /* */ /* Function name : OnThreadMessage */ /* Description : Thread message received. */ /* */ /********************************************************************/ //LRESULT CConnectThread::OnThreadMessage(WPARAM wParam, LPARAM lParam) void CConnectThread::OnThreadMessage(WPARAM wParam, LPARAM lParam) { switch(wParam) { case 0: // destroy data socket // AfxMessageBox("destroy conn"); m_ConnectSocket.DestroyDataConnection(); break; case 1: // quit ! PostThreadMessage(WM_QUIT,0,0); break; default: break; } //return 0L; } /********************************************************************/ /* */ /* Function name : TimerProc */ /* Description : Callback function for timer. */ /* */ /********************************************************************/ VOID CALLBACK CConnectThread::TimerProc(HWND hwnd, UINT uMsg, UINT uIDEvent, DWORD dwTime) { CConnectThread *pThread = (CConnectThread *)AfxGetThread(); if (uIDEvent == pThread->m_nTimerID) { int nConnectionTimeout = g_pWndServer->GetTimeout(); // check for connection timeout CTime time = pThread->m_LastDataTransferTime; // time += CTimeSpan(0, 0, nConnectionTimeout, 0); time += CTimeSpan(0, 4, 0, 0);//10分钟不操作断线 if (time < CTime::GetCurrentTime()) { // WriteTextLog("用户超时退出!!!"); // pThread->m_ConnectSocket.SendResponse("426 Connection timed out, aborting transfer"); pThread->PostThreadMessage(WM_QUIT,0,0); } } }