/****************************************************************/ /* */ /* 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 "LYFZReceiveMsgApp.h" #include "LYFZReceiveMsg.h" #include "ApplicationDlg.h" #include "ConnectThread.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif extern CLYFZReceiveMsg *g_pWndServer; CStringArray g_conniparray; CStringArray g_ipnoallowarray; 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. */ /* */ /********************************************************************/ //初始化线程 extern BOOL AddConn(CDatabase *m_conndb); int FindArray(CStringArray *pArray, CString Str) { int count=0; for(int i=0; iGetSize (); i++) { if(pArray->ElementAt (i)==Str) count++; } return count; } 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.m_pThread = this; CString strIPAddress; UINT nPort; m_ConnectSocket.GetPeerName(strIPAddress, nPort); m_strRemoteHost=strIPAddress; if(0) { int count=::FindArray(&g_conniparray, strIPAddress); if(count>20) { WriteLogin("连接超数ip:"+strIPAddress); PostThreadMessage(WM_QUIT,0,0); return 0; } g_conniparray.Add (strIPAddress); } // 把CSocket对象与socket句柄绑定 // 通知服务器一个新的连接到达 g_pWndServer->SendMessage(WM_THREADSTART, (WPARAM)this, 0); if(AddConn(&m_conndb)==0) { WriteLogin("打开新数据库连接失败"); PostThreadMessage(WM_QUIT,0,0); return 0; } m_conndb.SetQueryTimeout(5*60); m_ConnectSocket.m_pConndb=&m_conndb; // m_ConnectSocket.m_pConndb=&g_db; 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. */ /* */ /********************************************************************/ //线程终止 int CConnectThread::ExitInstance() { try { if(m_conndb.IsOpen()) m_conndb.Close(); 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); } 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 #ifdef VC60 ON_MESSAGE(WM_THREADMSG, OnThreadMessage) #else ON_THREAD_MESSAGE(WM_THREADMSG, OnThreadMessage) #endif 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. */ /* */ /********************************************************************/ #ifdef VC60 LRESULT 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; } #else 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; } #endif /********************************************************************/ /* */ /* 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, 0, 0, 60); if (time < CTime::GetCurrentTime()) { // pThread->m_ConnectSocket.SendResponse("426 Connection timed out, aborting transfer"); pThread->PostThreadMessage(WM_QUIT,0,0); } } }