/****************************************************************/ /* */ /* 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; i<pArray->GetSize (); i++) { if(pArray->ElementAt (i)==Str) count++; } return count; } extern CString g_localip; extern void GetOneConn(CDatabase **m_pdb, CArray<CDatabase*,CDatabase*>*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); WriteLogin(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) { WriteLogin("�������ݿ�����ʧ��"); PostThreadMessage(WM_QUIT,0,0); return 0; } m_conndb.SetQueryTimeout(60*2); m_ConnectSocket.m_pConndb=&m_conndb;*/ m_ConnectSocket.m_pdb=NULL; GetOneConn(&m_ConnectSocket.m_pdb, &m_ConnectSocket.m_dbarray, this); /* if (g_pWndServer->CheckMaxUsers()) { // m_ConnectSocket.SendResponse("421 Too many users are connected, please try again later."); WriteLogin("���ӳ����������");PostThreadMessage(WM_QUIT,0,0); } else if (!g_pWndServer->IsIPAddressAllowed(strIPAddress)) { // m_ConnectSocket.SendResponse("421 Access denied, IP address was rejected by the server."); WriteLogin("�Ƿ�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; //WriteLogin("�߳��˳�"); 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_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. */ /* */ /********************************************************************/ 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; } } /********************************************************************/ /* */ /* 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()) { // WriteLogin("�û���ʱ�˳�!!!"); // pThread->m_ConnectSocket.SendResponse("426 Connection timed out, aborting transfer"); pThread->PostThreadMessage(WM_QUIT,0,0); } } }