VC FTP服务器程序分析(二)

  上面讲到了CClientThread类,打开这个类的实现,这个类实现了4个函数。依次分析:

  1、InitInstance   其说明如下:InitInstance必须被重载以初始化每个用户界面线程的新实例。统称,你重载InitInstance函数来执行当线程首次被创建时必须完成的任务。此成员函数仅在用户界面线程中使用。

 1 BOOL CClientThread::InitInstance()
 2 {
 3     // Attach the socket handle to a CSocket object.
 4     // This makes sure that the socket notifications are sent to this thread.
 5     m_ControlSocket.Attach(m_hSocket);
 6     m_ControlSocket.m_pThread = this;
 7 
 8     // send welcome message to client
 9     m_ControlSocket.SendResponse("220 欢迎使用CC的FTP 服务器!!!");
10 
11     UINT nPort;
12     m_ControlSocket.GetPeerName(m_strPeerName, nPort);
13 
14     // dynamically allocate memory for IP address (receiver will delete it!)
15     int nLength = m_strPeerName.GetLength();
16     LPSTR lpszPeerName = new char[nLength+1];
17     lstrcpy(lpszPeerName, m_strPeerName);
18     
19     // Post a message to the main thread so that it can update the number of open connections
20     ::PostMessage(m_hWndOwner, WM_THREADSTART, (WPARAM)lpszPeerName, (LPARAM)m_nThreadID);
21     return TRUE;
22 }

  第5行,m_ControlSocket类关联了m_hSocket句柄,m_hSocket是在创建线程对象之后传递进来的。m_ControlSocket是与客户端通信使用的控制命令套接字。第9行,调用了m_ControlSocket的成员函数SendResponse。这里涉及到CControlSocket类,这个类下篇分析再讲。这里就是给客户端回复了一个信息,信息里面为什么是220,这里就是具体的通信协议了,后面再讲。

 第11至20,就是将客户端信息显示在主窗口上面了。

 2、ExitInstance  其说明如下:框架通过很少被重载的Run成员函数调用此函数以退出线程的这个实例;或者当调用InitInstance失败时,调用此函数。除了在Run成员函数内之外,不得在任何地方调用此成员函数。此成员函数仅被用户界面线程使用。当m_bAutoDelete为真时,此函数的缺省实现删除CWinThread对象。如果你希望当线程终止时执行额外的清除工作,请重载此函数。当你的程序代码被执行之后,你的ExitInstance实现应调用基类的ExitInstance函数。

 1 int CClientThread::ExitInstance()
 2 {
 3     // delete this thread from the linked list
 4     CServerDlg *pWnd = (CServerDlg *)AfxGetApp()->m_pMainWnd;
 5     if (pWnd != NULL)
 6     {
 7         pWnd->m_CriticalSection.Lock();
 8         POSITION pos = pWnd->m_ThreadList.Find(this);
 9         if(pos != NULL)
10         {
11             pWnd->m_ThreadList.RemoveAt(pos);
12         }
13         pWnd->m_CriticalSection.Unlock();
14     } 
15     // dynamically allocate memory for IP address (receiver will delete it!)
16     int nLength = m_strPeerName.GetLength();
17     LPSTR lpszPeerName = new char[nLength+1];
18     lstrcpy(lpszPeerName, m_strPeerName);
19     
20     // Post message to the main thread that this socket connection has closed
21     ::PostMessage(m_hWndOwner, WM_THREADCLOSE, (WPARAM)lpszPeerName, (LPARAM)m_nThreadID);
22     return CWinThread::ExitInstance();
23 }

  上面这个函数,第4至14行 删除了在界面类中保存的本线程对象指针。第16至21行,给界面发送了线程退出的消息。

  3、PostStatusMessage函数,此函数就是在给主窗口发送消息。

 1 void CClientThread::PostStatusMessage(LPCTSTR lpszStatus)
 2 {
 3     CString strData = lpszStatus;
 4 
 5     int nLength = strData.GetLength();
 6     
 7     // dynamically allocate memory for status message (receiver will delete it!)
 8     LPSTR lpszData = new char[nLength+1];
 9     lstrcpy(lpszData, strData);
10     ::PostMessage(m_hWndOwner, WM_ADDTRACELINE, (WPARAM)lpszData, (LPARAM)m_nThreadID); 
11 }

  WM_ADDTRACELINE从字面上看就是增加一条记录信息。

  4、OnDestroyDataConnection  这是一个消息响应函数,也就是一个线程对象如果去接收并处理一个消息,这就是个很好的例子了。

 1 BEGIN_MESSAGE_MAP(CClientThread, CWinThread)
 2     //{{AFX_MSG_MAP(CClientThread)
 3         // NOTE - the ClassWizard will add and remove mapping macros here.
 4     //}}AFX_MSG_MAP
 5     ON_THREAD_MESSAGE(WM_DESTROYDATACONNECTION, OnDestroyDataConnection)
 6 END_MESSAGE_MAP()
 7 
 8 
 9 void CClientThread::OnDestroyDataConnection(WPARAM wParam, LPARAM lParam)
10 {
11     m_ControlSocket.DestroyDataConnection();
12 }

  这里调用了CControlSocket类的成员函数DestroyDataConnection。下面就分析CConntrolSocket类的实现。

posted @ 2016-01-23 15:42  kanite  阅读(625)  评论(0编辑  收藏  举报