CListenSocket是CAsyncSocketEx类的子类,在启动的时候用来监听21端口。 pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, NULL)可见,CListenSocket只处理FD_ACCEPT消息。看一下:void CListenSocket::OnAccept(int nErrorCode){ CAsyncSocketEx socket; if (!Accept(socket)) // 这里调用了win API:accept方法,建立了一个新连接,socket就这个新连接的SOCKET { int nError =WSAGetLastError(); CStdString str; str.Format(_T("Failure inCListenSocket::OnAccept(%d) - call to CAsyncSocketEx::Accept failed,errorcode%d"), nErrorCode, nError); SendStatus(str, 1); SendStatus(_T("If you use a firewall, please check your firewall configuration"), 1); return; } // 权限检查,先不管 if (!AccessAllowed(socket)) { CStdStringAstr = "550 No connections allowed from your IP\r\n"; socket.Send(str, str.GetLength()); return; } // 检查FileZilla Server是否处于锁定状态,即不允许建立新连接 if (m_bLocked) { CStdStringA str = "421 Server is locked, please try again later.\r\n"; socket.Send(str, str.GetLength()); return; } // 下面从可用的线程中,找出目前负荷最小的线程,即线程中负责的connection最少的线程 int minnum =255*255*255; CServerThread *pBestThread=0;; for(std::list::iteratoriter=m_pThreadList->begin(); iter!=m_pThreadList->end(); iter++) { int num=(*iter)->GetNumConnections(); if (numIsReady()) // 找出connection最少的线程 { minnum=num; pBestThread=*iter; if (!num) break; } } if (!pBestThread) { char str[] = "421 Server offline."; socket.Send(str, strlen(str)+1); socket.Close(); return; } /* Disable Nagle algorithm. Most of the time single short stringsget * transferred over the control connection. Waiting foradditional data * where there will be most likely none affectsperformance. */ BOOL value = TRUE; socket.SetSockOpt(TCP_NODELAY, &value, sizeof(value), IPPROTO_TCP); //设置不使用Nagle算法,参见TCP协议Nagle算法部分 SOCKET sockethandle = socket.Detach(); pBestThread->AddSocket(sockethandle, m_ssl); // 转交服务线程来处理 CAsyncSocketEx::OnAccept(nErrorCode); // 父类的缺省处理为空}可见,CListenSocket::OnAccept主要工作是1、创建一个socket来接收新的客户端连接2、进行一些检查设置,如权限检查,Nagle算法设置等3、找到一个负荷最小的后台服务线程,由交那个线程处理为了更清楚服务线程CServerThread的机制,先看回顾一下当时这个服务线程是如何被创建的。CServer类的Create()片断: for (int i = 0; i { int index = GetNextThreadNotificationID(); //得到这个线程的一个标识,即在线程数组std::vectorm_ThreadNotificationIDs中的index CServerThread *pThread = newCServerThread(WM_FILEZILLA_SERVERMSG + index); m_ThreadNotificationIDs[index] = pThread; // If the CREATE_SUSPENDED flag is specified, thethread is created in a suspended state, // and will not run untilthe ResumeThread function is called. // If this value is zero, the thread runs immediately after creation. if(pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } }看一下pThread->Create(THREAD_PRIORITY_NORMAL,CREATE_SUSPENDED),由于CServerThread继承于CThread,因此调用了CThread的create:BOOL CThread::Create(int nPriority /*=THREAD_PRIORITY_NORMAL*/, DWORD dwCreateFlags /*=0*/){ m_hThread=CreateThread(0, 0, ThreadProc, this, dwCreateFlags, &m_dwThreadId); // 调用win api创建一个线程 if(!m_hThread) { delete this; return FALSE; } ::SetThreadPriority(m_hThread, nPriority); return TRUE;}注意创建线程的时候,指定线程的初始状态为CREATE_SUSPENDED。创建成功后,调用pThread->ResumeThread():DWORD CThread::ResumeThread(){ // 下面使用winAPI:ResumeThread启动这个线程,线程开动后, 会自动跑到ThreadProc函数(create时指定) DWORDres=::ResumeThread(m_hThread); // 这个函数过后,有两个线程在跑,一个是刚才的主线程,一个是刚启动的线程 if (!m_started) //主线程运行到这里,由于m_started还是0,所以通过下面的WaitForSingleObject,进行了等待状态 { WaitForSingleObject(m_hEventStarted, INFINITE); } return res;}刚启动的线程进入了ThreadProc函数:DWORD WINAPI CThread::ThreadProc(LPVOIDlpParameter){ // 在CreateThread时指定的参数LPVOIDlpParameter为this,即CThread return ((CThread *)lpParameter)->Run();}即运行Run方法:DWORD CThread::Run(){ InitInstance(); //这里CServerThread类重写了这个方法,因此进入CServerThread::InitInstance(),进行了一些内存变量的初始化 // The SetEvent function sets the specified event object to the signaled state. SetEvent(m_hEventStarted); //设置event为active,使得刚才在等待的主线程复活,继续CServer的启动工作 m_started = true; MSG msg; while (GetMessage(&msg, 0, 0, 0)) // 进入这个线程的消息循环 { TranslateMessage(&msg); if (!msg.hwnd) OnThreadMessage(msg.message, msg.wParam, msg.lParam); // 调用OnThreadMessage处理消息 DispatchMessage(&msg); } DWORD res=ExitInstance(); delete this; return res;}可见,服务器启动后,刚开始没有消息时,CServerThread在GetMessage()时进入了block状态,一旦有消息到来,这个服务线程就苏醒,接着处理消息。下面回到最初的CListenSocket::OnAccept(),最后调用了pBestThread->AddSocket(sockethandle, m_ssl); // 转交服务线程来处理仔细看一下后台的服务线程是如何处理消息的。void CServerThread::AddSocket(SOCKETsockethandle, bool ssl){ // 调用了父类的方法 PostThreadMessage(WM_FILEZILLA_THREADMSG, ssl ? FTM_NEWSOCKET_SSL : FTM_NEWSOCKET, (LPARAM)sockethandle);}接着:BOOL CThread::PostThreadMessage(UINT message, WPARAM wParam,LPARAM lParam){ // posts a message to the message queue of thespecified thread. BOOL res=::PostThreadMessage(m_dwThreadId,message, wParam, lParam);; ASSERT(res); return res;}PostThreadMessage是windows API,作用是把消息message发送到线程m_dwThreadId,根据前面的代码,在这里就是把消息WM_FILEZILLA_THREADMSG,以及参数FTM_NEWSOCKET,sockethandle发送到那个负荷最小的后台服务线程,由于在启动时,那个后台线程处于GetMessage()的block中,因此收到这个消息到,那个后台线程苏醒,接着调用OnThreadMessage来处理这个WM_FILEZILLA_THREADMSG消息。