参考资料:《TCP/IP网络编程》
一、基本概念
1、socket套接字
所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。
2、FTP通信协议
FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。此外,由于FTP传输效率非常高,在网络上传输大的文件时,一般也采用该协议。
默认情况下FTP协议使用TCP端口中的 20和21这两个端口,其中20用于传输数据,21用于传输控制信息。但是,是否使用20作为传输数据的端口与FTP使用的传输模式有关,如果采用主动模式,那么数据传输端口就是20;如果采用被动模式,则具体最终使用哪个端口要服务器端和客户端协商决定。
二、程序实现效果
ftp命令和该客户端登陆过程比对,接下来展示包括目录操作、文件上传和下载、断点续传、多线程下载等功能
目录操作:
ls -l:
文件上传:
文件下载:
断点续传:
三、实现原理
FTP使用2个TCP端口,首先是建立一个命令端口(控制端口),然后再产生一个数据端口。客户端从一个任意的非特权端口N(N>1024)连接到FTP服务器的命令端口(即tcp 21端口)。紧接着客户端开始监听端口N+1,并发送FTP命令“port N+1”到FTP服务器。最后服务器会从它自己的数据端口(20)连接到客户端指定的数据端口(N+1),这样客户端就可以和ftp服务器建立数据传输通道了。
四、代码分析
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "ftp_client.h"
// 创建FTP客户端对象
FTPClient* ftp = NULL;
void sigint(int num)
{
if(ftp->is_get)
{
printf("------------------------\n");
close(ftp->cli_pasv);
close(ftp->cli_sock);
close(ftp->fd);
set_mtime(ftp->file,ftp->mtime);
printf("------------------------\n");
}
if(ftp->is_put)
{
close(ftp->cli_pasv);
close(ftp->fd);
mdtm_FTPClient(ftp);
close(ftp->cli_sock);
}
exit(EXIT_SUCCESS);
}
int main(int argc,const char* argv[])
{
signal(SIGINT,sigint);
if(2 == argc)
{
ftp = create_FTPClient(argv[1],21);
}
else if(3 == argc)
{
short port = atoi(argv[2]);
ftp = create_FTPClient(argv[1],port);
}
else
{
printf("use:ftp xxx.xxx.xxx.xxx [port]\n");
return EXIT_SUCCESS;
}
// 输入用户名
char user[20] = {
};
printf("Name:");
get_str(user,sizeof(user));
user_FTPClient(ftp,user);
// 密码并登录
char pass[20] = {
};
printf("Password:");
get_passwd(pass,sizeof(pass),0);
pass_FTPClient(ftp,pass);
// 循环的输入命令、执行命令
char cmd[256] = {
};
for(;;)
{
printf("ftp> ");
get_str(cmd,sizeof(cmd));
if(0 == strncmp("pwd",cmd,3))
{
pwd_FTPClient(ftp);
}
else if(0 == strncmp("cd ",cmd,3))
{
cd_FTPClient(ftp,cmd+3);
}
else if(0 == strncmp("mkdir ",cmd,6))
{
mkdir_FTPClient(ftp,cmd+6);
}
else if(0 == strncmp("ls",cmd,2))
{
ls_FTPClient(ftp);
}
else if(0 == strncmp("put ",cmd,4))
{
put_FTPClient(ftp,cmd+4);
}
else if(0 == strncmp("get ",cmd,4))
{
get_FTPClient(ftp,cmd+4);
}
else if(0 == strncmp("bye",cmd,3))
{
bye_FTPClient(ftp);
destory_FTPClient(ftp);
return EXIT_SUCCESS;
}
else if('!' == cmd[0])
{
system(cmd+1);
}
else
{
printf("指针未定义!!!\n");
}
}
}
main函数:
设置各个的功能的函数入口,同时注册一个信号函数用于异常退出
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <utime.h>
#include <getch.h>
#include <sys/types.h>
#i