IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 简单的ftp服务器(客户端、服务器端、socket) -> 正文阅读

[数据结构与算法]简单的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函数在服务器端我用了相对地址,直接用文件名不行(没有找到原因),还有就是这个服务端接入一个客户端还好,但是接入多个客户端就不知道要把信息发给谁(这个问题没有处理)。
  • 如果后面后时间的话,还想为服务器增添一些登录验证的功能,用链表存内每个用户的信息,用户注册可以插入链表,用户注销可以删掉链表,管理员还可以查找用户信息等等功能,看看现在学习到的东西还很少,还要努力呀!!
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:51:09  更:2021-07-11 16:51:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 18:35:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码