简单的ftp服务器(客户端、服务器端、socket)

查看本机IP地址:

  • 127.0.0.1

服务器功能:

  • 可以获取服务器文件使用get指令
  • 可以展示服务器有哪些文件使用ls指令
  • 进入服务器某个文件夹使用指令cd+文件夹名称
  • 上传本地文件到服务器,使用指令put
  • pwd可以查看客户端在当前服务器的位置

客户端本地功能:

  • lls查看客户端本地文件
  • lcd+文件名,进入客户端某个文件
  • lpwd可以查看当前客户端自己的路径
  • help可查看服务器支持指令
  • quit退出服务器

写代码的时候要写一个功能编译验证一下,不要把所有功能都写完后再编译验证,不容易调试。

简易FTP服务端代码:

#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

#define LS   0
#define PWD  1

#define GET  2
#define PUT  3
#define CD   4
#define HELP 5
#define QUIT 6
#define OUT  7

typedef struct Client
{
        char cmd[128];
        char databuf[1024];
}Cli,*Pcli;
char* getcmd(char* cmd)
{
        char* re=NULL;
        re=strtok(NULL," ");
        return re;
}
char* firstcmd(char* cmd)
{
        char*p;
        p=strtok(cmd," ");
        return p;
}
int changmsg(Pcli msg)
{
        char*cmd=firstcmd(msg->cmd);
        if(strcmp("ls",msg->cmd)==0)          return LS;
        if(strcmp("pwd",msg->cmd)==0)         return PWD;
        if(strcmp("help",msg->cmd)==0)        return HELP;
        if(strcmp("quit",msg->cmd)==0)        return QUIT;
        if(strcmp("get",cmd)==0)              return GET;
        if(strcmp("put",cmd)==0)              return PUT;
        if(strcmp("cd",cmd)==0)               return CD;
}
int receHandle(int fd,Pcli msg)
{
        int ret;
        int size;
        int openfd;
        char* new;
        char newfilename[128];
        char* filename;
        FILE* file;
        ret=changmsg(msg);
        switch(ret){
                case PWD:
                case LS:
                        file=popen(msg->cmd,"r");
                        memset(msg,'\0',sizeof(Cli));
                        fread(msg->databuf,1,1024,file);
                        write(fd,msg,sizeof(Cli));
                        fclose(file);
                        break;
                case PUT:
                        filename=getcmd(msg->cmd);
                        openfd=open(filename,O_RDWR|O_CREAT,0660);
                        printf("file has made\n");
                        write(openfd,msg->databuf,strlen(msg->databuf));
                        close(openfd);
                        break;
                case GET:
                        filename=getcmd(msg->cmd);
                        if(access(filename,F_OK)==0){
                                openfd=open(filename,O_RDWR);
                                size=lseek(openfd,0,SEEK_END);
                                lseek(openfd,0,SEEK_SET);
                                memset(msg->databuf,'\0',1024);
                                read(openfd,msg->databuf,size*sizeof(char));
                                printf("send:%s\n",msg->databuf);
                                write(fd,msg,sizeof(Cli));
                                close(openfd);
                        }
                        else{
                                memset(msg->cmd,'\0',128);
                                strcpy(msg->cmd,"no");
                                write(fd,msg,sizeof(Cli));
                        }
                        break;
                case CD:
                        filename=getcmd(msg->cmd);
                        sprintf(newfilename,"./%s",filename);
                        if(access(newfilename,F_OK)==0){
                                memset(msg->cmd,'\0',128);
                                strcpy(msg->cmd,"yes");
                                write(fd,msg,sizeof(Cli));
                                chdir(newfilename);
                        }
                        else{
                                memset(msg->cmd,'\0',128);
                                strcpy(msg->cmd,"no");
                                write(fd,msg,sizeof(Cli));
                        }
                        break;
                case HELP:
                        memset(msg,'\0',sizeof(Cli));
                        strcpy(msg->databuf,"cd\nlcd\nls\nlls\npwd\nlpwd\nput\nget\nhelp");
                        write(fd,msg,sizeof(Cli));
                        break;
                case QUIT:
                        close(fd);
                        return OUT;
                        break;
        }
}

int main()
{
        int bindre;
        int newfd;
        int re;
        int socketre;
        int listenre;
        pid_t fpid;
        Cli msg;
        struct sockaddr_in IP;
        struct sockaddr_in CLI;//客户端信息
        int len=sizeof(struct sockaddr_in);
        memset(&IP,'\0',len);
        memset(&CLI,'\0',len);
        IP.sin_family=AF_INET;
        IP.sin_port=htons(8686);
        IP.sin_addr.s_addr=inet_addr("192.168.1.198");
        socketre=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if(socketre==-1){
                printf("create fail\n");
                perror("socket");
                exit(-1);
        }
        bindre=bind(socketre,(struct sockaddr*)&IP,len);
        if(bindre==-1){
                perror("bind");
                printf("bind fail\n");
                exit(-1);
        }
        listenre=listen(socketre,10);
        if(listenre==-1){
                printf("listen fail\n");
                perror("listen");
                exit(-1);
        }
        while(1){
                newfd=accept(socketre,(struct sockaddr*)&CLI,&len);
                if(newfd==-1){
                        perror("accept");
                        printf("accept fail\n");
                        exit(-1);
                }
                printf("get client:%s\n",inet_ntoa(CLI.sin_addr));
                fpid=fork();
                if(fpid==0){
                        while(1){
                                memset(&msg,'\0',sizeof(Cli));
                                if(read(newfd,&msg,sizeof(Cli))!=0){
                                        re=receHandle(newfd,&msg);
                                        if(re==OUT){
                                                printf("client is quit!\n");
                                                break;
                                        }
                                }
                                else {
                                        printf("Error! Don't connect!\n");
                                        break;
                                }
                        }
                }

                if(fpid>0){
                        waitpid(fpid,NULL,WNOHANG | WUNTRACED);
                }
        }
        return 0;
}

服务端代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#define LS   0
#define PWD  1
#define GET  2
#define PUT  3
#define CD   4
#define HELP 5
#define NO   6
#define LCD  7
#define LLS  8
#define LPWD 9
#define QUIT 10
#define OUT 11
typedef struct Client
{
        char cmd[128];
        char databuf[1024];
}Cli,*Pcli;
char* getcmd(char* cmd)
{
        char* p;
        p=strtok(cmd," ");
        return p;
}
int changmsg(Pcli snd)
{
        char* cmd=firstcmd(snd->cmd);
        if(strcmp("lls",snd->cmd)==0)         return LLS;
        if(strcmp("quit",snd->cmd)==0)        return QUIT;
        if(strcmp("ls",snd->cmd)==0)          return LS;
        if(strcmp("pwd",snd->cmd)==0)         return PWD;
        if(strcmp("quit",snd->cmd)==0)        return QUIT;
        if(strcmp("lpwd",snd->cmd)==0)        return LPWD;
        if(strcmp("help",snd->cmd)==0)        return HELP;
        if(strcmp(cmd,"get")==0)              return GET;
        if(strcmp(cmd,"put")==0)              return PUT;
        if(strcmp(cmd,"cd")==0)               return CD;
        if(strcmp(cmd,"lcd")==0)              return LCD;
        return NO;
}
int client_Handle(int fd,Pcli snd)
{
        int ret;
        int openfd;
        int size;
        char newcmd[128];
        char* filename;
        strcpy(newcmd,snd->cmd);
        ret=changmsg(snd);
        switch(ret){
                case LLS:
                        printf("---------------------------------------------------------");
                        putchar('\n');
                        system("ls");
                        putchar('\n');
                        printf("---------------------------------------------------------\n");
                        break;
                case LPWD:
                        printf("---------------------------------------------------------");
                        putchar('\n');
                        system("pwd");
                        putchar('\n');
                        printf("---------------------------------------------------------\n");
                        break;
                case  PWD:
                case  LS:
                case HELP:
                        write(fd,snd,sizeof(Cli));
                        read(fd,snd,sizeof(Cli));
                        printf("---------------------------------------------------------");
                        putchar('\n');
                        printf("%s",snd->databuf);
                        putchar('\n');
                        printf("---------------------------------------------------------\n");
                        memset(snd,'\0',sizeof(Cli));
                        break;
                case PUT:
                        filename=getcmd(snd->cmd);
                        if(access(filename,F_OK)==0){
                                openfd=open(filename,O_RDWR);
                                size=lseek(openfd,0,SEEK_END);
                                lseek(openfd,0,SEEK_SET);
                                memset(snd->databuf,'\0',1024);
                                read(openfd,snd->databuf,sizeof(char)*size);
                                memset(snd->cmd,'\0',128);
                                strcpy(snd->cmd,newcmd);
                                write(fd,snd,sizeof(Cli));
                                close(openfd);
                        }
                        else{
                                printf("文件不存在\n");
                        }
                        break;
                case GET:
                        filename=getcmd(snd->cmd);
                        strcpy(snd->cmd,newcmd);
                        write(fd,snd,sizeof(Cli));
                        memset(snd->databuf,'\0',1024);
                        read(fd,snd,sizeof(Cli));
                        if(strcmp(snd->cmd,"no")==0){
                                printf("No This File!\n");
                        }
                        else{
                                openfd=open(filename,O_RDWR|O_CREAT,0660);
                                write(openfd,snd->databuf,strlen(snd->databuf));
                                close(openfd);
                        }
                        break;
                case CD:
                        memset(snd->cmd,'\0',128);
                        strcpy(snd->cmd,newcmd);
                        write(fd,snd,sizeof(Cli));
                        memset(snd->cmd,'\0',128);
                        read(fd,snd,sizeof(Cli));
                        if(strcmp(snd->cmd,"no")==0){
                                printf("File isn't exist!\n");
                        }
                        else{
                                printf("get:%s\n",snd->cmd);
                        }
                        break;
                case LCD:
                        filename=getcmd(snd->cmd);
                        if(access(filename,F_OK)==0){
                                chdir(filename);
                        }
                        else{
                                printf("Under the path,dont't have this file!\n");
                        }
                        break;
                case NO:
                        printf("command isn't exist.\n");
                        break;
                case QUIT:
                        strcpy(snd->cmd,"quit");
                        write(fd,snd,sizeof(Cli));
                        close(fd);
                        return OUT;
                        break;
        }
}
int main()
{
        int socketfd;
        int conre;
        int handre;
        char cmd[128];
        char*writebuf;
        char*readbuf;
        char mark[128];
        Cli sendmsgr;
        struct Client CL;
        struct sockaddr_in addr;
        addr.sin_family=AF_INET;
        addr.sin_port=htons(8686);
        addr.sin_addr.s_addr=inet_addr("192.168.1.198");
        socketfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if(socketfd==-1){
                printf("socket create fail\n");
                perror("socket");
                exit(-1);
        }
        conre=connect(socketfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in));
        if(conre==-1){
                printf("connect fail\n");
                perror("connect");
                exit(-1);
        }
        printf("hanve conected server...\n");
        while(1){
                memset(&sendmsgr,'\0',sizeof(Cli));
                printf(">");
                fgets(cmd,128,stdin);
                strncpy(sendmsgr.cmd,cmd,strlen(cmd)-1);
                printf("cmd:%s\n",sendmsgr.cmd);
                handre=client_Handle(socketfd,&sendmsgr);
                if(handre==OUT){
                        printf("server is quit!\n");
                        exit(0);
                }
        }

        return 0;
}

学习体会补充:

  • read是有返回值n的,如果n>0,那么就可以读到BUF里去,n=0,说明客户端发送了FIN信号,就断开连接,n<0,说明发生了中断或者错误。
  • 学习到新的函数chdir和access的用法,更加深入的了解socket网络编程函数的使用,巩固了之前文件系统那里学习到的函数,对结构体和指针的使用更加熟练,总的来说,代码不难但是第一次那么长的代码,还是有点小难度的,只要注意客户端和服务端传递参数的时候要保证发送和接收的类型一样就好,这里我就用了结构体来存放发送的信息,那么接收也要用结构体,注意初始化,还有就是write的时候最好有多少东西就写多少东西不然内容后面会有很多乱码,chdir函数在服务器端我用了相对地址,直接用文件名不行(没有找到原因),还有就是这个服务端接入一个客户端还好,但是接入多个客户端就不知道要把信息发给谁(这个问题没有处理)。
  • 如果后面后时间的话,还想为服务器增添一些登录验证的功能,用链表存内每个用户的信息,用户注册可以插入链表,用户注销可以删掉链表,管理员还可以查找用户信息等等功能,看看现在学习到的东西还很少,还要努力呀!!
简单FTP服务器,供大家参考.版本 2 命令文本 = 到大写 (到文本 (服务器1.取回数据 ())) 命令文本 = 子文本替换 (命令文本, #换行符, , , , 真) .判断开始 (取文本左边 (命令文本, 4) = “USER”) ' 用户名 .如果真 (PASS (命令文本)) 服务器1.发送数据 (客户信息, “331 ” + #换行符, ) 返回 () .如果真结束 服务器1.发送数据 (客户信息, “530 ” + #换行符, ) .判断 (取文本左边 (命令文本, 4) = “PASS”) ' 密码,这里采用匿名的方式登陆 .如果真 (匿名) 服务器1.发送数据 (客户信息, “230 ” + #换行符, ) 返回 () .如果真结束 服务器1.发送数据 (客户信息, “530 ” + #换行符, ) .判断 (命令文本 = “OPTS UTF8 ON”) ' 路径采用UTF8编码 ' UTF8编码 = 真 服务器1.发送数据 (客户信息, “503 ” + #换行符, ) ' 暂时不支持utf8编码 .判断 (命令文本 = “SYST” 或 命令文本 = “SITE HELP”) 服务器1.发送数据 (客户信息, “215 近在眼前 FTP Server” + #换行符, ) .判断 (命令文本 = “PWD”) 服务器1.发送数据 (客户信息, “257 ” + #引号 + 目录 + #引号 + #换行符, ) .判断 (命令文本 = “TYPE A”) .如果真 (文件号 ≠ 0) 关闭文件 (文件号) 文件号 = 0 .如果真结束 服务器1.发送数据 (客户信息, “200 ” + #换行符, ) .判断 (取文本左边 (命令文本, 3) = “CWD”) ' 改变工作目录 .如果 (取文本长度 (命令文本) > 5) 服务器1.发送数据 (客户信息, “550 近在眼前友情提示:目前还不支持改变目录!” + #换行符, ) .否则 服务器1.发送数据 (客户信息, “250 ” + #引号 + 目录 + #引号 + #换行符, ) .如果结束 .判断 (命令文本 = “PASV”) ' 采用被动方式连接 IP = PASV (端口) 服务器2.端口 = 端口 服务器1.发送数据 (客户信息, “227 Entering Passive Mode (” + IP + “)” + #换行符, ) .判断 (命令文本 = “LIST”) ' 列表 服务器1.发送数据 (客户信息, “150 ” + #换行符, ) 发送数据 = 发送列表 (根目录 + 目录) 服务器2.发送数据 (数据客户, 发送数据, ) 服务器2.断开客户 (数据客户) 服务器1.发送数据 (客户信息, “226 Transfer complete” + #换行符, ) .判断 (命令文本 = “NOOP”) 服务器1.发送数据 (客户信息, “200 ” + #换行符, ) .判断 (命令文本 = “TYPE I”) 服务器1.发送数据 (客户信息, “200 ” + #换行符, ) .判断 (命令文本 = “SIZE”) 服务器1.发送数据 (客户信息, “421 ” + #换行符, ) .判断 (取文本左边 (命令文本, 4) = “QUIT”) 服务器1.发送数据 (客户信息, “220 再来我揍你!” + #换行符, ) 服务器1.断开客户 (客户信息) .默认 服务器1.发送数据 (客户信息, “550 近在眼前友情提示:暂时不支持该功能!” + #换行符, ) ' 其它命令你们自行扩展,这里暂时屏蔽
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值