📄 myftp.c
字号:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<pthread.h>
#include<fcntl.h>
#define BACKLOG 5
#define ASSCI 0
#define BIN 1
#define SPEED 512
#define SUC_FLAG "USER Certification Successed!"
#define FAIL_FLAG "USER Certification Failed!"
#define data_len 1024;
#define cmd_len 50;
#define mput_limit 10;
#define mget_limit 10;
//******
struct clientinfo{
char name[10];
char passwd[6];
};
//*****
// 变量
int sockfd,datasockfd;
char comstr[512];
char testget[12];
char help[]="\t**************************************\n\t*ls--显示当前路径所有文件或目录信息*\n\t*lpwd--显示当前所在路径 *\n\t*lmkdir--在当前路径下创建一个目录 *\n\t*lrmdir--删除当前路径下一个目录 *\n\t*lcd --切换所处的路径 *\n\t*put --上传文件到服务器 *\n\t*get --从服务器下载文件 *\n\t*quit--退出当前用户 *\n\t**************************************\n";;
pthread_t my_pthread;
// 函数
struct sockaddr_in make_remoteaddr(int,int);
int init_link(int,int);
int download_from_server(int sockfd,char *filename,int type);
int put_client2server(int clientfd,char *filename,int type);
void my_op(void* arg);
void clear_n(char *str);
int main(int argc,char *argv[]){
if(argc == 1||argc >2){
perror("start failed.\n");
return -1;
}
if (argc == 2) {
char arg[512] ="";
char usrname[512] = "";
char psword[512] = "";
char serip[512] = "";
char port[512] = "";
get_param(argv[1],usrname,psword,serip,port);
short int *_port;
_port =(short int *) port;
//输入正确,开始初始化
if(!strcmp(serip,"0")){
sockfd = init_link(*_port,0);
datasockfd = init_link(*_port+1,0);
}
else{
sockfd = init_link(*_port,inet_addr(serip));
datasockfd = init_link(*_port+1,inet_addr(serip));
}
//printf("ip %d",inet_addr(serip));
write(sockfd,argv[1],512);
//相应操作
char valiteflag[512]="";
read(datasockfd,valiteflag,512);
if (strcmp(valiteflag,SUC_FLAG)) {
printf("userme doesn't exist or password is error!\n");
_exit(0);
}
else
printf("verify successfuly...\n");
sleep(1);
printf("\t\twelcome to my ftp\n\n");
sleep(1);
printf("%s",help);
if(sockfd != -1){
//perror("init succeed.\n");
pthread_create(&my_pthread,NULL,(void *)&my_op,(void*)&sockfd); //创建客户操作线程
pthread_join(my_pthread,NULL);//操作线程非分离
return 0;
}
else if(sockfd == -1){
perror("init failed.\n");
return -1;
}
}
}
int init_link(int port,int ip){
int fd,sockfd;
int len,ret,retval;
struct sockaddr_in remoteaddr;
// printf("port is %d\nip is %d\n",port,ip);
// printf("\t\twelcome to myftp\n");
printf("Connecting...\n");
sleep(1);
sockfd = socket(AF_INET,SOCK_STREAM,0);//创建套接字
if(sockfd == -1){
printf("sock_fd create error.");
return -1;
}
// printf("ip %d",ip);
remoteaddr = make_remoteaddr(port,ip);//绑定远程地址和端口
if(connect(sockfd,(struct sockaddr *)&remoteaddr,sizeof(remoteaddr))!=0){//连接
printf("connect error.\n");
return -1;
}
return sockfd;
}
struct sockaddr_in make_remoteaddr(int port,int ip){ //具体绑定函数
struct sockaddr_in remoteaddr;
bzero(&remoteaddr,sizeof(struct sockaddr_in));
//memset(remoteaddr.sin_zero,'0',sizeof(remoteaddr.sin_zero));
char *str = remoteaddr.sin_zero;
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_port = port;
// printf("ip %d",ip);
if(ip == 0)
remoteaddr.sin_addr.s_addr = INADDR_ANY;
else if(ip != 0)
remoteaddr.sin_addr.s_addr = ip;
return remoteaddr;
}
void my_op(void *arg){
int *sockfd;
char deal_result[1024*40]="";
sockfd = (int *)arg;
char *cmd_arg_array[512]={""}; // 存放命令及参数
int cmd_arg_mount=0; // 记录命令参数个数
int _sockfd = *sockfd;
printf("myftp>");
fgets(comstr,sizeof(comstr),stdin);
while(1){
clear_n(comstr);
write(_sockfd,comstr,512);
// printf("A is %d\n",_sockfd);
// printf("comstr is %s\n",comstr);
cmd_arg_mount=get_argc_argv(comstr,cmd_arg_array);
if(!strcmp(cmd_arg_array[0],"put")){
printf("get command put\n");
if(cmd_arg_mount == 2)
put_client2server(datasockfd,cmd_arg_array[1],0);//未解析
if(cmd_arg_mount ==3){
if(!strcmp(cmd_arg_array[2],"assci")||!strcmp(cmd_arg_array[2],"ASSCI") )
put_client2server(datasockfd,cmd_arg_array[1],0);
else if(!strcmp(cmd_arg_array[2],"bin")||!strcmp(cmd_arg_array[2],"BIN") )
put_client2server(datasockfd,cmd_arg_array[1],1);
}
else {
perror("enter error!");
}
}
if(!strcmp(cmd_arg_array[0],"get")){
printf("get command get\n");
if(cmd_arg_mount == 2)
download_from_server(datasockfd,cmd_arg_array[1],0);//未解析
else if(cmd_arg_mount ==3){
if(!strcmp(cmd_arg_array[2],"assci")||!strcmp(cmd_arg_array[2],"ASSCI") )
download_from_server(datasockfd,cmd_arg_array[1],0);
else if(!strcmp(cmd_arg_array[2],"bin")||!strcmp(cmd_arg_array[2],"BIN") )
download_from_server(datasockfd,cmd_arg_array[1],1);
} else{
perror("enter error!");
}
}
if (!strcmp(comstr,"quit")) {
break;
}
read(datasockfd,deal_result,1024*40);
// printf("B is %d\n",datasockfd);
printf("%s\n",deal_result);
memset(deal_result,0,sizeof(deal_result));
printf("myftp>");
fgets(comstr,sizeof(comstr),stdin);
}
}
//下面是下载函数可以使用,但有些要求要继续实现,如断点续传,判断下载路径,此功能在函数完成后添加
//以下为客户端代码
int download_from_server(int sockfd,char *filename,int type){ //从服务器上下载
FILE *file_download;int temp_fd,new_fd,nget,filelen;
char download_buf[SPEED];
if(type == 0){ //0为ASSCI类型下载
printf("ASSCI type.\n");
file_download = fopen(filename,"w");
}
if(type == 1){//1为二进制下载
printf("BIN type.\n");
file_download = fopen(filename,"wb");
}
temp_fd = fileno(file_download);
int download = 0;
read(sockfd,&filelen,sizeof(int));
printf("filelen=%d\n",filelen);
do{ //由于写代码用的ubuntu没有带eof功能,所以用是否读完判断是否下载结束
if (SPEED>filelen-download) {
nget = read(sockfd,download_buf,filelen-download);
download+=nget;
printf("%d char finished.\n",download);
printf("Download file %s finished.\n",filename);
fclose(file_download);
close(temp_fd);
return 0;
}
nget = read(sockfd,download_buf,SPEED);
write(temp_fd,download_buf,nget);
download +=nget;
if(nget != 0){
printf("%d char finished.\n",download);
}
usleep(500000);
}while(nget > 0);
}
int put_client2server(int clientfd,char *filename,int type){ //上传到服务器
int newfd,nread,nput;
FILE *fileput;
char put_buf[SPEED];
if(type == 0){
fileput = fopen(filename,"r");
if(fileput == NULL){
perror("assci fopen error.\n");
return -1;
}
}
if(type == 1){
fileput = fopen(filename,"rb");
if(fileput == NULL){
perror("bin fopen error.\n");
return -1;
}
}
printf("start to put...");
sleep(2);
newfd = fileno(fileput);
int filelen;
lseek(newfd,0,SEEK_SET);
filelen = lseek(newfd,0,SEEK_END); //获取下载内容长度
lseek(newfd,0,SEEK_SET); //将文件指针置到文件开始
printf("filelen is %d.\n",filelen);
nput = 0;
write(clientfd,&filelen,sizeof(int));
do{
nread = read(newfd,put_buf,SPEED);
write(clientfd,put_buf,nread);
nput+=nread;
usleep(500000);
if(nread > 0){
printf("%d byte put.\n",nput);
}
if(nput == filelen){
printf("put finished.\n");
close(newfd);
fclose(fileput);
return 0;
}
}while(nread > 0);
}
// 已测试
// 实例:get_str_between("abc",str,0,2)后的str="ab"
int get_str_between(char *str,char *strcpy,int start,int end) {
if (start > end) return -1;
int i = 0;
for (;i<=strlen(strcpy);i++) {
strcpy[i] = '\0';
}
i = start;
for (;i<=end;i++) {
strcpy[i-start] = str[i];
}
strcpy[i-start-1]='\0';
return end-start+1;
}
void clear_n(char *str) {
if (str[strlen(str)-1] == '\n') {
str[strlen(str)-1] = '\0';
}
}
// 已测试
int get_argc_argv(char *cmd,char* arg_array[]) {
char array[512][512]={""};
int strlength;
char strcmd[512] = "";
strcpy(strcmd,cmd);
strlength = strlen(strcmd);
int st_index = 0;
int end_index = 0;
int mount = 0;
while (st_index <= strlength) {
while (end_index <= strlength && strcmd[end_index] == ' ') {
end_index++;
}
if (end_index > strlength) break;
st_index = end_index;
while (end_index <= strlength && strcmd[end_index] != ' ' ) {
end_index++;
}
mount++;
get_str_between(strcmd,array[mount-1],st_index,end_index);
arg_array[mount-1]=array[mount-1];
st_index = end_index;
}
return mount;
}
int get_index_of(char *str,char ch) {
int i = 0;
int flag = 0;
while(str[i] != ch && str[i]!='\0') {
i++;
};
if (str[i] != '\0') return i;
else return -1;
}
int get_strindex_of(char *str1,char *str2) {
int str1_len,str2_len;
str1_len = strlen(str1)-1;
str2_len = strlen(str2)-1;
if (str1_len < str2_len) return -1;
int start_index,flag,p;
for (start_index = 0;start_index<= str1_len-str2_len; start_index++) {
flag = 0; p = 0;
while(p <= str2_len && str1[start_index+p] == str2[p]) {
p++;
}
if (p>str2_len) return start_index;
}
return -1;
}
// 解析用户名、密码、服务器ip、端口
void get_param(char *cmd,char *usrname,char *psword,char *serverip,char *port) {
char server_add[20] = "";
int index_usr;
index_usr = get_index_of(cmd,'@');
get_str_between(cmd,server_add,index_usr+1,strlen(cmd));
get_str_between(cmd,usrname,0,get_index_of(cmd,':'));
get_str_between(cmd,psword,get_index_of(cmd,':')+1,index_usr);
get_str_between(server_add,serverip,0,get_index_of(server_add,':'));
get_str_between(server_add,port, get_index_of(server_add,':')+1,strlen(server_add));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -