基本FTP客户端
QT C++实现的FTP下载客户端
环境说明
FTP服务器:CentOS7.8 + vsFTPD 3.0.2 安装设置见博文
CentOS vsftpd设置
客户端:win10+QT 5.15.2
实现的不是一个功能全的FTP客户端,而是程序中有从FTP服务器下载文件的需求,主要实现了下载的功能,包括断点续传,没有实现多线程下载。多线程下载的实现与断点续传有点关系,看懂了断点续传,实现多线程下载就简单了。
FTP协议是建立在TCP基础上的,在实现时用的就是Socket编程,客户端和服务端之间发送消息,消息的格式见上篇博文的最后几张图。
C++的简单FTP客户端实现(一)FTP基础知识
示例代码下载:
QT C++实现的FTP客户端,带断点续传功能
建立Socket连接
WSADATA dat;
int ret;
//初始化,很重要
if (::WSAStartup(MAKEWORD(2,2),&dat) != 0) //Windows Sockets Asynchronous启动
{
cout<<"Init Failed: "<<GetLastError()<<endl;
emit emitInfo(network , "Init Failed!n");
return -1;
}
//创建Socket
controlSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(controlSocket==INVALID_SOCKET)
{
cout<<"Creating Control Socket Failed: "<<GetLastError()<<endl;
emit emitInfo(network , "Creating Control Socket Failed.n");
return -1;
}
//构建服务器访问参数结构体
serverAddr.sin_family=AF_INET;
serverAddr.sin_addr.S_un.S_addr=inet_addr(ip_addr.c_str()); //地址
serverAddr.sin_port=htons(PORT); //端口
memset(serverAddr.sin_zero,0,sizeof(serverAddr.sin_zero));
//连接
ret = ::connect(controlSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
if(ret==SOCKET_ERROR)
{
cout<<"Control Socket Connecting Failed: "<<GetLastError()<<endl;
emit emitInfo(network , "Control Socket Connecting Failedn");
return -1;
}
用户名密码登录:
//用户名
executeCmd("USER " + username);
if(recvControl(331) != 0)
{
emit emitInfo(userpass, "");
}
//密码
executeCmd("PASS " + password);
if(recvControl(230) != 0)
{
emit emitInfo(userpass, "用户名或密码错误!");
return -1;
}
更改目录
executeCmd("CWD "+tardir);
if(recvControl(250) != 0)
{
emit emitInfo(directory, "FTP目录不存在!");
return -1;
}
切换Binary模式
memset(buf, 0, BUFLEN);
executeCmd("TYPE I");
if(recvControl(200) != 0)
{
emit emitInfo(filename, "切换BINARY模式失败!");
return -1;
}
列出当前目录下所有文件
int FtpClient::listPwd()
{
intoPasv();
executeCmd("LIST -al");
recvControl(150);
memset(databuf, 0, DATABUFLEN);
string fulllist;
int ret = recv(dataSocket, databuf, DATABUFLEN-1, 0);
while(ret>0)
{
databuf[ret] = '