要聯結到FTP伺服器,需要兩個步驟,首先必須建立一個CInternetSession對象,用類CInterSession建立並初始化一個或幾個同時存在的Internet會話(session),並描述與Proxy 伺服器的串連(如果有必要的話),如果在程式運行期間需要保持與Internet的串連,可以建立一個CInternetSession對象作為類CWinApp的成員。 ---- MFC中的類CFtpConnection管理我們與Internet伺服器的串連,並直接動作伺服器上的目錄和檔案,FTP是MFC的WinInet支援的三個Internet功能之一,我們需要先建立一個CInternetSession執行個體和一個CFtpConnection對象就可以實現和一個FTP伺服器的通訊,我們不需要直接建立CFtpConnection對象,而是通過調用CInternetSession::GetFtpConnection來完成這項工作。它建立CFtpConnection對象並返回一個指向該對象的指標。 Ftp串連類的資訊 ---- 下面我們簡要介紹串連類的資訊 1. CInternetSession對象 ---- CInternetSession(LPCTSTR pstrAgent,DWORD dwConText ,DWORD dwAccessType,LPCTSTR pstrProxyName,LPCTSTR pstrProxyBypass,DWORD dwFlags); ---- 在建立CInternetSession對象時調用這個成員函數,CInternetSession是應用程式第一個要調用的Internet函數,它將創始化內部資料結構,以備將來在應用程式中調用。如果dwFlags包含INTERNET_FLAG_ASYNC,那末從這個控制代碼派生的所有的控制代碼,在狀態回調常式注冊之前,都會出現非同步狀態。如果沒有開啟Internet串連,CInternetSession就會拋出一個例外,AfxThorowInternetException。 2. GetFtpConnection()函數 ---- CFtpConnection* CIternetSession::GetFtpConnection(LPCTSTR pstrServer,LPCTSTR pstrUserName,LPCTSTR pstrPassword,INTERNET_PORT nPort,BOOL bPassive); ---- 調用這個函數建立一個FTP串連,並獲得一個指向CFtpConnection對象的指標,GetFtpConnection串連到一個FTP伺服器,建立並返回指向CFtpConnection對象的指標,它不在伺服器上進行任何操作。如果打算讀寫檔案,必須進行分步操作。關於尋找,開啟和讀/寫檔案的資訊需參考CFtpConnection和CFtpFileFind類。 ---- 對這個函數的調用返回一個指向CFtpConnection對象的指標。如果調用失敗,檢查拋出的CInternetException對象,就可以確定失敗的原因。 3. GetFile()函數 ---- BOOL GetFile(LPCTSTR pstrRemoteFile,LPCTSTR pstrLocalFile,BOOL bFailExists ,DWORD dwAttributes,DWORD dwFlags,DWORD dwContext); ---- 調用這個成員函數,可以從FTP伺服器取得檔案,並且把檔案儲存在本地機器上。GetFile()函數是一個比較進階的常式,它可以處理所有有關從FTP伺服器讀檔案,以及把檔案存放在本地機器上的工作。如果dwFlags為FILE_TRANSFER_TYPE_ASCII,檔案資料的傳輸也會把控制和格式符轉化為Windows中的等階符號。預設的傳輸模式是二進位模式,檔案會以和伺服器上相同的格式被下載。 ---- pstrRemoteFile和 pstrLocalFile可以是相對於目前的目錄的部分檔案名稱,也可以是全檔案名稱,在這兩個名字中間,都既可以用反斜線(/)或者正斜杠(/)來作為檔案名稱的目錄分隔字元,GetFile()在使用前會把目錄分隔字元轉化為適當的字元。 ---- 可以用自己選擇的值來取代dwContext預設的值,設定為上下文標識符與CFtpConnection對象的定位操作有關,這個操作由CFtpConnection中的CInternetSession對象建立。返回給CInternetSession::OnStatusCallBack的值指出了所標識操作的狀態。 ---- 如果調用成功,函數的返回為非0,否則返回0,如果調用失敗,可以調用Win32函數GetLastError(),確認出錯的原因。 4. PutFile()函數 ---- BOOL PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoveFile ,DWORD dwFlags, DWORD dwContext); ---- 調用這個成員函數可以把檔案儲存到FTP伺服器。PutFile()函數是一個比較進階的常式,它可以處理有關把檔案存放到伺服器上的工作。只發送資料,或要嚴格控制檔案傳輸的應用程式,應該調用OpenFile和 CInternet::Write。利用自己選擇的值來取代dwContext預設的值,設定為上下文標識符,上下文標識符是CInternetSession對象建立的CFtpConnection對象的特定操作有關,這個值返回給CInternetSession::OnStateCallBack,從而把操作的狀態通報給它所標識的上下文。 ---- 如果調用成功,函數的返回為非0,否則返回0,如果調用失敗,可以調用Win32函數GetLastError(),確認出錯的原因。 串連到FTP網站 ---- 建立串連到ftp.microsoft.com的程式,它是一個單文檔程式。並且串連由視圖類的建構函式完成。 1. 建立單文檔程式ftp 2. 在ftpview.h中加入包含#include < afxinet.h > 3. 在ftpview.h中添加如下的成員變數 4. public: 5. CInternetSession *m_pInetSession; 6. CFtpConnection *m_pFtpConnection; 7. 在ftpview.cpp中的ftpview建構函式中加入下面的代碼 8. CFtpView::CFtpView() 9. { 10. m_pInetSession=new CInternetSession 11. (AfxGetAppName(),1, 12. PRE_CONFIG_INTERNET_ACCESS); 13. try 14. { 15. m_pFtpConnection=m_pInetSession-> 16. GetFtpConnection("FTP.MICROSOFT.COM"); 17. } 18. catch(CInternetException *pEx) 19. { 20. TCHAR szError[1024]; 21. if(pEx->GetErrorMessage(szError,1024)) 22. AfxMessageBox(szError); 23. else 24. AfxMessageBox("There was an exception"); 25. pEx->Delete(); 26. m_pFtpConnection=NULL; 27. } 28. } 29. 在ftpview.cpp中的ftpview解構函式中加入下面的代碼 30. CFtpView::~CFtpView() 31. { 32. if(m_pFtpConnection!=NULL) 33. { 34. m_pFtpConnection->Close(); 35. delete m_pFtpConnection; 36. } 37. delete m_pInetSession; 38. } 39. 編譯並且執行程式,如果串連出現問題,將會在一個訊息框中報告出錯訊息。 傳送檔案到FTP檔案伺服器 ---- 建立一個傳送檔案到FTP檔案伺服器的程式 40. 建立單文檔程式ftpfw, 在ftpfwview.h中加入包含 #include < afxinet.h > 41. 在ftpfwview.h中添加如下的成員變數 42. public: 43. bool m_bConnectionAttempted; 44. int m_nFileStatus; 45. 在ftpview.cpp中的ftpview建構函式中加入下面的代碼 46. CFtpfwView::CFtpfwView() 47. { 48. m_bConnectionAttempted=false; 49. } 50. 使用ClassWizard加入新的類CFtpThread,該類派生於CWinThread 在ftpthread.h中加入如下變數 51. public: 52. static UINT PutFile(LPVOID Status); 53. 添加新類成員函數代碼 54. UINT CFtpThread::PutFile(LPVOID Status) 55. { 56. int *pnFileStatus; 57. CInternetSession *pInetSession; 58. CFtpConnection *pFtpConnection=NULL; 59. pnFileStatus=(int *)Status; 60. *pnFileStatus=0; 61. pInetSession=new 62. CInternetSession(AfxGetAppName(),1, 63. PRE_CONFIG_INTERNET_ACCESS); 64. try 65. { 66. pFtpConnection=pInetSession-> 67. GetFtpConnection("192.34.45.0"); 68. } 69. catch(CInternetException *pEx) 70. { 71. pEx->Delete(); 72. pFtpConnection=NULL; 73. *pnFileStatus=-1; 74. goto BallOut; 75. } 76. *pnFileStatus =1; 77. pFtpConnection->Remove("test.txt"); 78. if(!pFtpConnection->PutFile 79. ("test.txt","test.txt")) 80. *pnFileStatus=-2; 81. else 82. *pnFileStatus=2; 83. BallOut: 84. if(pFtpConnection!=NULL) 85. { 86. pFtpConnection->Close(); 87. delete pFtpConnection; 88. } 89. delete pInetSession; 90. AfxEndThread(0); 91. return false; 92. } 93. 編輯ftpfwview.cpp中的OnDraw()函數 94. void CFtpfwView::OnDraw(CDC* pDC) 95. { 96. CFtpfwDoc* pDoc = GetDocument(); 97. ASSERT_VALID(pDoc); 98. if(!m_bConnectAttempted) 99. { 100. m_bConnectAttempted=TRUE; 101. AfxBeginThread((AFX_THREADPROC) 102. CFtpThread::PutFile,&m_nFileStatus); 103. } 104. } 105. 編譯並且執行程式,在串連和傳輸的過程中,應用程式仍然可以作自己的工作,這是因為傳輸的過程發生線上程中。 總結語 ---- 通過以上的程式我們可以明白FTP的工作原理,我們可以編製自己的獲得FTP伺服器的檔案以及獲得FTP伺服器的根目錄,親自體驗一下我們的程式工作的怎末樣。
|