本次实验的工程文件下载:https://gryffinbit.lanzous.com/idK4Hj7kb4b
实验目标
程序能实现基本的 FTP 客户机端功能,能登录 FTP 服务器,显示登录客户机目录下的文件和 目录名,能从该目录中选择下载服务器的文件,也能向服务器上传文件。
实验目的
- 学习如何创建一个 Internet 会话,即创建 CInternetSession 对象;
- 学习如何建立与 FTP 服务器的连接, 即创建 CFtpConnection 对象;如果连接成功,如何获得当前登录的目录下的文件和目录名称,即 检索一个目录下的文件,并显示文件信息;如何下载文件、上传文件以及关闭连接。
实验环境
Windows10 x64,Visual Studio 2017
实验内容
应用程序的类型是基于对话框的。
对话框中包括三个文本框,分别用于输入 FTP 服务器域名、登录用户名和登录口令;一个列 表框,用来显示 FTP 服务器当前目录的内容,并允许用户从中选择文件下载;四个命令按钮,分 别执行查询、上传、下载和退出的操作。
实验原理(模型)
WinInet 类编程的一般步骤如下。
(1)创建 CInternetSession 类对象,创建并初始化 Internet 会话。
(2)利用 CInternetSession 类的 QueryOption 或 SetOption 成员函数,可以查询或设置该类内 含的 Internet 请求选项,这一步是可选的,不需要可以不做。
(3)创建连接类对象,建立 CInternetSession 对象与网络服务器的连接,也就是应用程序与网 络服务器的连接。只需要分别调用 CInternetSession 类的 GetFtpConnection、GetHttpConnection 或 GetGopherConnection 函数就可以轻松地创建 CFtpConnection 类、CHttpConnection 类或 CGopher Connection 类的对象实例。再使用这些对象实例的成员函数就能完成很多对于网络服务器的操作。 例如,对于 FTP 服务器,可以获知或设置当前目录,下载或上传文件,创建或删除目录,重命名 文件或目录等。
(4)创建文件检索类对象,对服务器进行检索。
(5)如果需要使用异步操作模式,可以重载 CInternetSession 类的 OnStatusCallback 函数,并 启动应用程序,使用状态回调机制,重载相关函数,加入自己的代码。
(6)如果还想更紧密地控制对服务器文件的访问,可以进一步创建文件类对象实例,完成文 件查找或文件读写操作。
(7)创建 CInternetException 类对象实例,处理错误。
(8)关闭各种类,将资源释放给系统。
实验过程
1.使用 MFC AppWizard 创建应用程序框架
应用程序类:CFtpApp,对应的文件是 Ftp.h 和 Ftp.cpp。
对话框类:CFtpDlg,对应的文件是 FtpDlg.h 和 FtpDlg.cpp。
2.为对话框添加控件
3.定义控件的成员变量
4.添加成员变量的初始化代码
在 FtpDlg.cpp 文件的 OnInitDialog( )函数中添加成员变量的初始化代码。对服务器名、登录用户名和登录口令的控件变量赋初值。
1 2 3 4 5 6 7
| m_strFtp = _T(""); m_strName = _T(""); m_strPwd = _T(""); m_strPwd = _T(""); UpdateData(FALSE); return TRUE;
|
5.为对话框中的控件对象添加事件响应函数
6.为 CFtpDlg 类添加其他的成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| BOOL CFtpDlg::Download(CString strSName, CString strDName) {
CInternetSession* pSession; CFtpConnection* pConnection;
pConnection = NULL;
pSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);
try { pConnection = pSession->GetFtpConnection(m_strFtp, m_strName, m_strPwd); } catch (CInternetException* e) { e->Delete(); pConnection = NULL; return FALSE; }
if (pConnection != NULL) { if (!pConnection->GetFile(strSName, strDName)) { pConnection->Close(); delete pConnection; delete pSession; return FALSE; } }
if (pConnection != NULL) { pConnection->Close(); delete pConnection; } delete pSession;
return TRUE; }
BOOL CFtpDlg::Upload(CString strSName, CString strDName) { CInternetSession* pSession; CFtpConnection* pConnection;
pConnection = NULL;
pSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);
try { pConnection = pSession->GetFtpConnection(m_strFtp, m_strName, m_strPwd); } catch (CInternetException* e) { e->Delete(); pConnection = NULL; return FALSE; }
if (pConnection != NULL) { if (!pConnection->PutFile(strSName, strDName)) { pConnection->Close(); delete pConnection; delete pSession; return FALSE; } }
if (pConnection != NULL) { pConnection->Close(); delete pConnection; }
delete pSession; return TRUE; }
|
7.手工添加包含语句
在 CFtpDlg 类的 FtpDlg.cpp 文件中添加对于 Afxinet.h 的包含命令,来获得对于 MFC WinInet 类的支持。
8.添加事件函数和成员函数的代码
FTP.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
#pragma once
#ifndef __AFXWIN_H__ #error "include 'pch.h' before including this file for PCH" #endif
#include "resource.h"
class CFtpApp : public CWinApp { public: CFtpApp();
public: virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP() };
extern CFtpApp theApp;
|
FTP.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
#include "pch.h" #include "framework.h" #include "Ftp.h" #include "FtpDlg.h"
#ifdef _DEBUG #define new DEBUG_NEW #endif
BEGIN_MESSAGE_MAP(CFtpApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP()
CFtpApp::CFtpApp() { m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
}
CFtpApp theApp;
BOOL CFtpApp::InitInstance() { INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
CShellManager *pShellManager = new CShellManager;
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
CFtpDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { } else if (nResponse == IDCANCEL) { } else if (nResponse == -1) { TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n"); TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n"); }
if (pShellManager != nullptr) { delete pShellManager; }
#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS) ControlBarCleanUp(); #endif
return FALSE; }
|
FtpDlg.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
#pragma once
class CFtpDlg : public CDialogEx {
public: CFtpDlg(CWnd* pParent = nullptr);
#ifdef AFX_DESIGN_TIME enum { IDD = IDD_FTP_DIALOG }; #endif
protected: virtual void DoDataExchange(CDataExchange* pDX);
protected: HICON m_hIcon;
virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: CStatic m_staFtp; CStatic m_staName; CStatic m_staPwd; CEdit m_editFtp; CString m_strFtp; CEdit m_editName; CString m_strName; CEdit m_editPwd; CString m_strPwd; CButton m_btnQuery; CButton m_btnDownload; CButton m_btnUpload; CListBox m_listFile; afx_msg void OnQuery(); afx_msg void OnDownload(); afx_msg void OnUpload(); afx_msg void OnSelchangeListFile(); BOOL Download(CString strSName, CString strDName); BOOL Upload(CString strSName, CString strDName); };
|
ftpDlg.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| BOOL CFtpDlg::Download(CString strSName, CString strDName) {
CInternetSession* pSession; CFtpConnection* pConnection;
pConnection = NULL;
pSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);
try { pConnection = pSession->GetFtpConnection(m_strFtp, m_strName, m_strPwd); } catch (CInternetException* e) { e->Delete(); pConnection = NULL; return FALSE; }
if (pConnection != NULL) { if (!pConnection->GetFile(strSName, strDName)) { pConnection->Close(); delete pConnection; delete pSession; return FALSE; } }
if (pConnection != NULL) { pConnection->Close(); delete pConnection; } delete pSession;
return TRUE; }
BOOL CFtpDlg::Upload(CString strSName, CString strDName) { CInternetSession* pSession; CFtpConnection* pConnection;
pConnection = NULL;
pSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);
try { pConnection = pSession->GetFtpConnection(m_strFtp, m_strName, m_strPwd); } catch (CInternetException* e) { e->Delete(); pConnection = NULL; return FALSE; }
if (pConnection != NULL) { if (!pConnection->PutFile(strSName, strDName)) { pConnection->Close(); delete pConnection; delete pSession; return FALSE; } }
if (pConnection != NULL) { pConnection->Close(); delete pConnection; }
delete pSession; return TRUE; }
|
9.进行测试
需要先在本机开启FTP服务器
filezilla sever开启FTP服务。
下载链接:
https://gryffinbit.lanzous.com/i5ISij3kh6f
安装后,点击edit,setting进行基本配置。14147为默认端口
在filezilla设置用户端。
添加一个用户。
在服务器域名文本框中输入“localhost”,保持登录用户名和口令与刚刚创建的用户一致,单击“查询”按钮,用户将获得 FTP 服务器的默认目录下的文件名和目录名。
实验界面结果展示
界面显示:
下载文件:
实验过程中遇到的问题
字符问题,在字符串前面,加上_T
1
| strFileName = _T("[" )+ strFileName + _T("]");
|