课程设计:用wininet接口写的FTP Client

本文介绍了如何使用Wininet接口编写一个简单的FTP客户端程序,该程序采用MFC进行图形化界面设计,支持连接、列表、下载、退出等基本FTP命令。程序具有IP地址合法性检测、多线程下载、异常处理等功能,遵循RFC959协议,且具备良好的编程规范和注释。文章详细展示了关键代码实现,包括连接、解析地址、登陆、退出、文件列表获取、下载和上传等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目1  FTP客户端

编写一个简单的FTP客户机程序,要求能够向FTP服务器发送命令,并接收FTP服务器返回的响应与数据。程序设计的具体要求如下:

1)要求实现的程序为图形化界面(如图下所示),可以输入FTP服务的相关信息(包括IP地址、用户名与密码),输出交互过程中的FTP命令与响应信息,以及从FTP服务器的根目录获得的文件(或目录)列表。

2)要求遵循RFC959的相关FTP协议规定。只要求实现USER、PASS、PASV、LIST、RETR和QUIT命令。点击Connect按钮,实现USER与PASS命令;点击List按钮,实现PASV 与LIST命令;点击Download按钮,实现PASV 与RETR命令;点击Quit按钮,实现QUIT命令。

3)支持IP地址、域名输入,及合法性检测,显示FTP登录过程,下载速率等。

4)支持多线程下载,实现线程管理,显示各线程的状态。报告各种异常,提示产生异常的原因。

5)要求有良好的编程规范与注释信息。

6)要求有详细的说明文档,包括程序的设计思想、工作流程、关键问题等。

7)要求在Windows操作系统环境中,建议使用Visual C++编程工具实现。



一.详细设计

我之所以选择使用wininet的接口,是因为用它来开发的话会比较简单和快速。

(1)界面布局


(2)为Connect,List,Download,Upload,Quit,<-等button添加BN_CLICKED事件以及编写事件函数

(3)代码的编写集中CFtpClientDlg类里,下面就详细介绍一下这个类的代码:

1.几个常量:

//存储所有文件类型
const char fielType[8][9] = {"归档文件","文件夹","隐藏文件","普通文件","只读文件","系统文件","临时文件","其他文件"};
const int BUF_SIZE = 4096 ;
const int MSG_SIZE = 1024 ;

2.CFTPClientDlg的变量

        CFont edit_font;

CInternetSession m_InternetSession;  //定义一个会话对象
CFtpConnection *m_pFtpConnection;   //连接对象指针
HANDLE m_hEventKill;        //事件句柄


CString m_sFTPServerCurFolder;         //FTP服务器当前目录
CString m_sFTPServerParentFolder;    //FTP服务器当前目录的父目录


DWORD dwLastErrorMsg;                      //应答码
DWORD dwErrorMsgSize;     //应答信息长度
char  buf[MSG_SIZE];     //应答信息


CString strServer;                                    //服务器地址
        CString strRemoteFile;                          //选中的远程文件地址
CString strLocalFile;                              //存储在本地的文件地址
int     nItem;                                              //选中项的索引
int     selectedFileType;                         //选中文件的类型
long    fileLen;                                         //选中文件的长度
long    downloadSize;                           //当前下载量
bool    isSelected;                                 //是否选中 

3.CFTPClientDlg的构造函数

CFTPClientDlg::CFTPClientDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFTPClientDlg::IDD, pParent)
{
//{ {AFX_DATA_INIT(CFTPClientDlg)
m_Address = _T("");
m_Password = _T("");
m_User = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
edit_font.CreateFont(
18,   //字体大小
0,0,0,FW_NORMAL,  
FALSE,FALSE,  
0,  
ANSI_CHARSET,              // nCharSet
OUT_DEFAULT_PRECIS,        // nOutPrecision
CLIP_DEFAULT_PRECIS,       // nClipPrecision
DEFAULT_QUALITY,           // nQuality
        DEFAULT_PITCH | FF_SWISS, "Arial");

m_pFtpConnection = NULL;
m_hEventKill = CreateEvent (NULL, TRUE, FALSE, NULL);


m_sFTPServerCurFolder = "/";
m_sFTPServerParentFolder = "/";

dwLastErrorMsg = 0;
dwErrorMsgSize = MSG_SIZE;


strServer = "";
strRemoteFile = "";
strLocalFile = "";

nItem = 0;
selectedFileType = 0;
fileLen = 0;
downloadSize = 0;
        isSelected = FALSE;


// Set the timeout value to 10 seconds
m_InternetSession.SetOption (INTERNET_OPTION_CONNECT_TIMEOUT, 10000);
m_InternetSession.SetOption (INT

把.h文件里面的代码放出来一下,CPP就不放了,自己下载哦。 #ifndef Download_h__ #define Download_h__ #include <wininet.h> #pragma comment(lib,"wininet.lib") class CHttpGet { public: //测试网络是否连接成功。 BOOL TestNetworkIsConnected(); //动态获取URL的文件名。 //LPCTSTR szURL URL地址 //LPSTR pFileName 文件名缓冲区,获取到文件名后,会文件名放入到该buffer //DWORD dwBufferOfLenght pFileName缓冲区大小。 //pResult 是否成功。 BOOL HttpGetFileName(LPCTSTR szURL,LPSTR pFileName,DWORD dwBufferOfLenght,BOOL * pResult); //将文件下载到缓冲区,而不是保存到文件 //szURL URL地址 //szBuffer 缓冲区。 //dwSize 缓冲区大小 //lpdwSizeOfRet实际下载到的数据大小。 DWORD URLDownloadToBuffer(LPCTSTR szURL,LPBYTE szBuffer,DWORD dwSize,DWORD *lpdwSizeOfRet); //下载文件 //szURL URL地址 //szFileSavePath 文件完整保存路径 // CheckFileTypeIsPe 是否需要检测文件是不是PE文件。 DWORD URLDownloadToFile(LPCTSTR szURL,LPCTSTR szFileSavePath,BOOL CheckFileTypeIsPe); }; #endif // Download_h__ CPP部分代码,详细自己下载。 完全原创。代码注释详细。 使用及其方便... DWORD CHttpGet::URLDownloadToFile(LPCTSTR szURL,LPCTSTR szFileSavePath,BOOL CheckFileTypeIsPe) { if(!CheckUrl(szURL)) return FALSE; HINTERNET hInternetOpen = InternetOpen( "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)", INTERNET_OPEN_TYPE_PRECONFIG,/*返回注册表中代理或直接的配置*/ NULL,//不使用代理 所以不要设置用户名 NULL,//不使用代理 所以不用设置密码 NULL ); if(hInternetOpen == NULL) return FALSE; HINTERNET hInternetUrl = InternetOpenUrl( hInternetOpen, szURL, "Accept: */*",//支持左所有文件 -1, INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE,/*不要从缓冲里面获取数据 */ NULL); if(hInternetUrl == NULL) return FALSE; CHAR szStatus[1024]={NULL}; DWORD dwBufferLen = sizeof(szStatus); //查询状态 HttpQueryInfo(hInternetUrl,HTTP_QUERY_STATUS_CODE,szStatus,&dwBufferLen;,NULL); //4xx(请求错误) DWORD dwCode = atoi(szStatus); if( dwCode > 400 && dwCode < 500) return FALSE; //5xx(服务器错误) if( dwCode >500 && dwCode < 600) return FALSE; //开始下载文件 HANDLE hFile = CreateFile(szFileSavePath,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile == INVALID_HANDLE_VALUE) { InternetCloseHandle(hInternetUrl); InternetCloseHandle(hInternetOpen); return FALSE; } CHAR szReadBuffer[4096]={NULL}; DWORD dwInternetReadOfByte = 0; DWORD dwWriteByte = 0; BOOL bFirst = FALSE; BOOL bResult = TRUE; do { BOOL bRet = InternetReadFile(hInternetUrl,szReadBuffer,sizeof(szReadBuffer),&dwInternetReadOfByte;); //说明文件传送完了。 if(bRet == TRUE && dwInternetReadOfByte == 0) break; if(bFirst == FALSE && CheckFileTypeIsPe==TRUE) { bFirst = TRUE; if(((PIMAGE_DOS_HEADER)szReadBuffer)->e_magic!= IMAGE_DOS_SIGNATURE) { bResult = FALSE; break; } } WriteFile(hFile,szReadBuffer,dwInternetReadOfByte,&dwWriteByte;,NULL); } while (TRUE); CloseHandle(hFile); InternetCloseHandle(hInternetUrl); InternetCloseHandle(hInternetOpen); return bResult; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值