Linux系统学习笔记——ftp项目

导读:本篇文章讲解 Linux系统学习笔记——ftp项目,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

服务端server.c

#include<stdio.h>
#include<string.h>
#include<sys/types.h>          /* See NOTES */
#include<sys/socket.h>
#include<stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "config.h"
#include <sys/stat.h>
#include <fcntl.h>

int option_cmd(char *cmd)
{
        if ( ! (strcmp("ls",cmd)) )
                return LS;
        if ( ! (strcmp("pwd",cmd)) )
                return PWD;
        if ( ! (strcmp("quit",cmd)) )
                return QUIT;
        if ( strstr(cmd,"cd") != NULL  )
                return CD;
        if ( strstr(cmd,"get") != NULL ) // 得到完成命令 如:get config.h
                return GET;
        if ( strstr(cmd,"put") != NULL )
                return PUT;

}

char *GetDir(char *dircmd)
{
        char *p;
        p = strtok(dircmd," "); // 以空格为分割标志,分割指令字符串
        p = strtok(NULL," ");   // 以NULL为标记

        
        
        return p;
}

void message_handle(struct Message msg,int fd)
{
        char cmdbuf[1024] = {0};
        char *file = NULL;
        int file_fd;

        printf("Come from Client cmd is : %s\n",msg.data); // 来自客户端的指令

        int cmd = option_cmd(msg.data); // 把客户端的指令进行筛选分类

        switch(cmd)
        {
                case LS:
                case PWD:
                        msg.type = 0;
                        FILE *p = popen(msg.data,"r");  // 把 ls,pwd 命令打开读取数据,并打开内容
                        fread(msg.data,sizeof(msg.data),1,p); //把文件指针 p 中数据读取到msg.data中
                        write(fd,&msg,sizeof(msg)); // 发送数据到客户端进行显示
                        break;
                case QUIT:
                        printf("The Client die out!\n"); // 结束本次连接
                        printf("-------------------------\n");
                        exit(-1);
                case CD:
                        msg.type = 1; // 标记
                        char *dir = GetDir(msg.data); // 分割命令字符串
                        printf("The dir is : %s\n",dir); // 把这个命令打印出来
                        chdir(dir);     // chdir函数直接执行分割出来的指令 如:../
                        break;
                case PUT:
                        file_fd = open(GetDir(msg.data),O_CREAT|O_RDWR,0666);
                          write(file_fd,msg.msgbuf,strlen(msg.msgbuf));
                        close(file_fd);
                        break;
                case GET:
                        file = GetDir(msg.data); // 对指令进行字符串分割处理

                        if(access(file,F_OK) == -1) // 判断是否有这个文件,失败返回-1
                        {
                                strcpy(msg.data,"Sorry,The file no have");
                                write(fd,&msg,sizeof(msg)); //把数据发送到客户端
                        }
                        else
                        {
                                msg.type = DOFILE; //标记方便客户端使用

                                file_fd = open(file,O_RDWR); // 用读取到的指令,打开一个新文件描述符
                                read(file_fd,cmdbuf,sizeof(cmdbuf)); // 把这个文件指令的数据进行读入数组
                                close(file_fd);         // 关闭文件

                                strcpy(msg.data,cmdbuf); // 把数组的内容拷贝到结构体数据 data 数组中
                                write(fd,&msg,sizeof(msg)); // 把数据内容发送到客户端中

                        }
                        break;
        }
}

int main(int argc, char **argv)
{
        int s_fd;       //      服务端套接字对象
        int c_fd;       //      客户端套接字对象
        int nread;      //      存放读取数据的大小

          struct Message msg;     //      创建Message结构体对象

        struct sockaddr_in s_addr;      //      创建两个结构体对象
        struct sockaddr_in c_addr;

        memset(&s_addr,0,sizeof(struct sockaddr_in));   //      为新申请内存,初始化结构体对象值
        memset(&c_addr,0,sizeof(struct sockaddr_in));

        // 1.socket

        s_fd = socket(AF_INET,SOCK_STREAM,0);   // 创建服务端套接字对象

        if(s_fd == -1)  // 检查创建对象是否成功
        {
                printf("create socket failed!\n");
                perror("why:");
                exit(-1);
        }

        // 2.bind

        //      struct sockaddr_in
        //      {
        //               sa_family_t            sin_family; /* 协议族 */
        //               in_port_t              sin_port;   /* 端口号 */
        //               struct in_addr         sin_addr;   /* IP地址结构体*/
        //               unisgned               char sin_zero[8];  // 填充没实际意义,只为了和sockaddr结构体在内存中对齐,这样两者可相互转换
        //      };

        //      IP地址结构体需要指向 in_addr中按网络字节顺序排列的地址

        //      struct in_addr 
        //      {
        //              uint32_t       s_addr;     /* address in network byte order */
          //      };

        s_addr.sin_family = AF_INET;    //      将 socket 对象和ip地址、端口进行绑定    
        s_addr.sin_port = htons(atoi(argv[2])); //      把端口字符串形式转换成整型
        inet_aton(argv[1],&s_addr.sin_addr);

        // 绑定 IP地址和端口号,对象s_addr需要强制转成 struct sockaddr * 型
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        // 3.listen

        listen(s_fd,10);        // 监听客户端信号接入,设置最大接入的数量

        // 4.accept

        int len = sizeof(struct sockaddr_in);

        while(1)
        {
                // 当客户端信号接入成功,创建一个新的已连接socket套接字描述符对象
                c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&len);

                if(c_fd == -1)
                {
                        printf("accept client signal failed!\n");
                        perror("why error :");
                        exit(-1);
                }

                // 打印 ip 地址,把网络能识别的形式,转换成字符串输出
                printf("Connect Ip address is %s\n ",inet_ntoa(c_addr.sin_addr));

                if(fork() == 0) // 当接入了新的信号,才创建新的进程去跑这个客户端
                {
                           while(1)
                        {
                                memset(msg.data,0,sizeof(msg.data));    // 初始化接受命令数据的数据data

                                nread = read(c_fd,&msg,sizeof(msg));    // 读取来自客户端的命令数据

                                if( nread == 0) // 客户端没有输入指令
                                {
                                        printf("The Client no scanf data\n");
                                        break;
                                }
                                else if( nread == -1)   // 接受客户端指令失败
                                {
                                        printf("read Client data failed\n");
                                        exit(-1);
                                }
                                else if( nread > 0) // 接受客户端指令成功
                                {
                                        message_handle(msg,c_fd); // 发送到数据处理函数,进行分类处理
                                }
                        }

                }
        }
        close(s_fd);
        close(c_fd);

        return 0;
}
   

客户端client.c

#include<stdio.h>
#include <unistd.h>
#include<string.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
int option_cmd(char *cmd)
{
        if( !(strcmp("ls",cmd)) )
                return LS;

        if( !(strcmp("pwd",cmd)) )
                return PWD;

        if( !(strcmp("lls",cmd)) )
                return LLS;

        if( !(strcmp("quit",cmd)) )
                return QUIT;

        if( strstr(cmd,"get") )
                return GET;

        if( strstr(cmd,"put") )
                return PUT;

        if( !(strcmp("cd",cmd)) )
                return CD;

//      if( !(strcmp("lcd",cmd)) )
//              return LCD;

        if( strstr(cmd,"lcd"))
                return LCD;

        return -1;
}

char *GetDir(char *cmd)
{
        char *p;
        p = strtok(cmd," ");
        p = strtok(NULL," ");

        if( p == NULL)
        {
                return cmd;
        }

        return p;
}

int option_cmd_handle(struct Message msg,int fd)
{
        char *dir = NULL;               // 用于分割字符
        char buf[128] = {'\0'};         // 存放msg.data中的命令
        char cmdbuf[1024];              // 存放put 文件

        int CMD;                // 用于命令分配返回
        int file_fd;            // 用于存放得到的文件

        strcpy(buf,msg.data);   // 把输入的命令存放到buf, 主要用于 put、 lcd

        dir = GetDir(buf);      // 把指令进行字符串分割
       CMD = option_cmd(buf);  // 命令分类

        switch(CMD)
        {
                case LS:
                case PWD:
                        msg.type = 0; // 和服务端一样的标记
                        write(fd,&msg,sizeof(msg)); // 发送数据到socket对象c_fd
                        break;

                case CD:
                        msg.type = 1;
                        write(fd,&msg,sizeof(msg));
                        break;

                case LCD:
                //      dir = GetDir(buf); // 分割命令字符串
                        chdir(dir); // 直接打开分割后的命令
                        break;

                case QUIT:
                        strcpy(msg.data,"quit"); // 拷贝终止命令,终止连接
                        write(fd,&msg,sizeof(msg)); // 发送数据
                        close(fd); // 关闭连接
                        exit(-1);

                case LLS:
                        system("ls"); // 直接用system打开指令ls
                        break;

                case GET:
                        write(fd,&msg,sizeof(msg));
                        break;
               case PUT:
                        strcpy(cmdbuf,msg.data);

                //      dir = GetDir(cmdbuf); // 分割字符串命令

                        if(access(dir,F_OK) == -1) // 查看是否有这个文件
                        {
                                printf("The %s  file is no have\n",dir);
                        }
                        else
                        {
                                file_fd = open(dir,O_RDWR); // 打开新文件
                                read(file_fd,msg.msgbuf,sizeof(msg.msgbuf));    //读入数据到新文件
                                close(file_fd);         // 关闭文件

                                write(fd,&msg,sizeof(msg));     //发送数据到服务端获取该文件
                        }
                        break;
        }
        return CMD;
}

void message_handle(struct Message msg,int fd)
{
        int nread;
        int newfile_fd;
        struct Message Msg;

        nread = read(fd,&Msg,sizeof(Msg));

        if(nread == 0) // 判断是否连接好服务端信号
        {
                printf("The server die out ! \n");
                       exit(-1);
        }
        else if(Msg.type == DOFILE)
        {
                char *file = GetDir(msg.data);

                newfile_fd = open(file,O_RDWR|O_CREAT|0600);
                write(newfile_fd,Msg.data,strlen(Msg.data));

                printf("--------->");
                fflush(stdout);
        }
        else
        {
                printf("---------------------------------\n");
                printf("\n%s\n",Msg.data);      //打印命令执行情况
                printf("---------------------------------\n");

                fflush(stdout);
        }


}

int main(int argc, char **argv)
{
        int c_fd;
        int n_read;
        struct Message msg;

        // 1.socket

        c_fd = socket(AF_INET,SOCK_STREAM,0); // 创建客户端socket对象
             if(c_fd == -1) // 判断是否创建socket 对象失败,失败返回 -1
        {
                printf("Create socket failed\n");
                exit(-1);
        }

        struct sockaddr_in c_addr;
        memset(&c_addr,0,sizeof(struct sockaddr_in));

        c_addr.sin_family = AF_INET; // 设置ip协议
        c_addr.sin_port = htons(atoi(argv[2])); // 把argv[2]端口号字符串形式转为整型
        inet_aton(argv[1],&c_addr.sin_addr);    // 把 argv[1]的ip地址转换成网络能识别的形式

        // 2. connect
        // 连接服务端信号,连接成功返回 0

        if( connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1)
        {
                printf("Connect Server port failed\n");
                exit(-1);
        }
        else
        {
                printf("Connect Server OK !\n"); // 连接成功
        }

        while(1)
        {
                memset(msg.data,0,sizeof(msg.data)); // 初始化结构体存放命令数组

                gets(msg.data); // 客户输入命令

                printf("You scanf cmd is : %s\n ",msg.data); // 打印客户输入的命令

                       int cmd = option_cmd_handle(msg,c_fd); // 把命令进行分类处理

                if(cmd > IFGO) // 指 LLS 、LCD、 QUIT 、PUT 命令
                {
                        printf("------------------->");
                        fflush(stdout);
                        continue;
                }

                if( cmd == -1) // 命令输入错误,没有这个命令
                {
                        printf("The cmd is no have\n");
                        fflush(stdout);
                        continue;
                }

                // 分类成功,发送命令,进行命令内容打印
                message_handle(msg,c_fd);
        }

        return 0;
}
                                          

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/68461.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!