Linux 下c语言ftp服务器简单实现

来源:Lstri 发布时间:2018-11-21 15:26:27 阅读量:1045

原来的程序没有注释,最近这段时间在学习网络编程这块,就在网上找了个程序来学习,第一次找的程序下载下来后,编译没通过,刚接触网络,哪可能去排错误,况且代码那么长,一下让我退了下来,还是等以后有了基础,再回过头看它!


     然后就找到了这个程序,拿下来运行了下,然后读了读,自己加上了注释,希望能给跟我一样的新手一点帮助吧,里面有不恰当的地方请指出哈。


//client.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <fcntl.h>

 

#define N 256

 

typedef struct sockaddr SA;

 

void commd_help();

void commd_exit();

void commd_ls(struct sockaddr_in, char *);

void commd_get(struct sockaddr_in , char *);

void commd_put(struct sockaddr_in , char *);

 

int main(int argc, char *argv[])

{

    char commd[N];

    struct sockaddr_in addr;

    int len;

    bzero(&addr, sizeof(addr));     //将&addr中的前sizeof(addr)字节置为0,包括'\0'

    addr.sin_family = AF_INET;      //AF_INET代表TCP/IP协议

    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //将点间隔地址转换为网络字节顺序

    addr.sin_port = htons(8989);    //转换为网络字节顺序

    len = sizeof(addr);

 

    while(1)

    {

        printf("ftp>");

        bzero(commd,N);

        //fgets函数从stdin流中读取N-1个字符放入commd中

        if(fgets(commd,N,stdin) == NULL)

        {

            printf("Fgets Error!\n");

            return -1;

        }

 

        commd[strlen(commd)-1]='\0';    //fgets函数读取的最后一个字符为换行符,此处将其替换为'\0'

 

        printf("Input Command Is [ %s ]\n",commd);

 

        if(strncmp(commd,"help",4) == 0) //比较两个字符串前4个字节,若相等则返回0

        {

            commd_help();

        }else if(strncmp(commd, "exit",4) == 0)

        {

            commd_exit();

            exit(0);   //结束进程

        }else if(strncmp(commd, "ls" , 2) == 0)

        {

            commd_ls(addr, commd);

        }else if(strncmp(commd, "get" , 3) == 0)

        {

            commd_get(addr, commd);

        }else if(strncmp(commd, "put", 3) ==0 )

        {

            commd_put(addr, commd);

        }else

        {

            printf("Command Is Error!Please Try Again!\n");

        }

 

    }

    return 0;

}

 

void commd_help()

{

 

    printf("\n=------------------- Welcome to Use the Ftp ----------------=\n");

    printf("|                                                           |\n");

    printf("|  help : Display All Command for the Server                |\n");

    printf("|                                                           |\n");

    printf("|   exit: Quit The Sever                                    |\n");

    printf("|                                                           |\n");

    printf("|   ls : Display All file On the Ftp Server                 |\n");

    printf("|                                                           |\n");

    printf("| get <file>: Download FIle from the Ftp Server             |\n");

    printf("|                                                           |\n");

    printf("| put <file>: Upload FIle to the Ftp Server                 |\n");

    printf("|                                                           |\n");

    printf("=-----------------------------------------------------------=\n");

 

    return ;

}

 

void commd_exit()

{

    printf("Byte!\n");

}

 

void commd_ls(struct sockaddr_in addr, char *commd)

{

    int sockfd;

    //创建套接字

    if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)

    {

        printf("Socket Error!\n");

        exit(1);

    }

 

    if(connect(sockfd, (SA *)&addr, sizeof(addr)) < 0)

    {

        printf("Connect Error!\n");

        exit(1);

    }

    //将commd指向的内容写入到sockfd所指的文件中,此处即指套接字

    if(write(sockfd, commd, N) < 0)

    {

        printf("Write Error!\n");

        exit(1);

    }

 

    while(read(sockfd, commd, N) > 0)  //从sockfd中读取N字节内容放入commd中,

    {                                   //返回值为读取的字节数

        printf(" %s ",commd);

    }

    printf("\n");

 

    close(sockfd);

    return ;

}

/**************************************************/

/*函数功能:实现文件的下载                            */

/**************************************************/

void commd_get(struct sockaddr_in addr, char *commd)

{

    int fd;

    int sockfd;

    char buffer[N];

    int nbytes;

    //创建套接字,并进行错误检测

    if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)

    {

        printf("Socket Error!\n");

        exit(1);

    }

    //connect函数用于实现客户端与服务端的连接,此处还进行了错误检测

    if(connect(sockfd, (SA *)&addr, sizeof(addr)) < 0)

    {

        printf("Connect Error!\n");

        exit(1);

    }

    //通过write函数向服务端发送数据

    if(write(sockfd, commd, N) < 0)

    {

        printf("Write Error!At commd_get 1\n");

        exit(1);

    }

    //利用read函数来接受服务器发来的数据

    if(read(sockfd, buffer, N) < 0)

    {

        printf("Read Error!At commd_get 1\n");

        exit(1);

    }

    //用于检测服务器端文件是否打开成功

    if(buffer[0] =='N')

    {

        close(sockfd);

        printf("Can't Open The File!\n");

        return ;

    }

    //open函数创建一个文件,文件地址为(commd+4),该地址从命令行输入获取

    if((fd=open(commd+4, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0)

    {

        printf("Open Error!\n");

        exit(1);

    }

    //read函数从套接字中获取N字节数据放入buffer中,返回值为读取的字节数

    while((nbytes=read(sockfd, buffer, N)) > 0)

    {

        //write函数将buffer中的内容读取出来写入fd所指向的文件,返回值为实际写入的字节数

        if(write(fd, buffer, nbytes) < 0)

        {

            printf("Write Error!At commd_get 2");

        }

    }

 

    close(fd);

    close(sockfd);

 

    return ;

 

}

/**************************************************/

/*函数功能:实现文件的上传                            */

/**************************************************/

void commd_put(struct sockaddr_in addr, char *commd)

{

    int fd;

    int sockfd;

    char buffer[N];

    int nbytes;

    //创建套接字

    if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)

    {

        printf("Socket Error!\n");

        exit(1);

    }

    //客户端与服务端连接

    if(connect(sockfd, (SA *)&addr, sizeof(addr)) < 0)

    {

        printf("Connect Error!\n");

        exit(1);

    }

    //从commd中读取N字节数据,写入套接字中

    if(write(sockfd, commd, N)<0)

    {

        printf("Wrtie Error!At commd_put 1\n");

        exit(1);

    }

    //open函数从(commd+4)中,读取文件路径,以只读的方式打开

    if((fd=open(commd+4, O_RDONLY)) < 0)

    {

        printf("Open Error!\n");

        exit(1);

    }

    //从fd指向的文件中读取N个字节数据

    while((nbytes=read(fd, buffer, N)) > 0)

    {

        //从buffer中读取nbytes字节数据,写入套接字中

        if(write(sockfd, buffer, nbytes) < 0)

        {

            printf("Write Error!At commd_put 2");

        }

    }

 

    close(fd);

    close(sockfd);

 

    return ;

}



    下面server.c中后面有些注释没加,感觉功能上跟client相似,就没加,可以参看前面的

//server.c

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <dirent.h>

#include <fcntl.h>

 

#define N 256

 

typedef struct sockaddr SA;

 

void commd_ls(int);

void commd_get(int, char *);

void commd_put(int, char *);

 

int main(int arg, char *argv[])

{

    int ser_sockfd,cli_sockfd;

    struct sockaddr_in ser_addr,cli_addr;

    int ser_len, cli_len;

    char commd [N];

    bzero(commd,N);//将commd所指向的字符串的前N个字节置为0,包括'\0'

 

    if((ser_sockfd=socket(AF_INET, SOCK_STREAM, 0) ) < 0)

    {

        printf("Sokcet Error!\n");

        return -1;

    }

 

    bzero(&ser_addr,sizeof(ser_addr));

    ser_addr.sin_family = AF_INET;

    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);//在TCP连接中,此处类似于自动获取ip地址

                                                //在绑定ip时,自动选择ip地址

    ser_addr.sin_port = htons ( 8989 );

    ser_len = sizeof(ser_addr);

    //将ip地址与套接字绑定

    if((bind(ser_sockfd, (SA *)&ser_addr, ser_len)) < 0)

    {

        printf("Bind Error!\n");

        return -1;

    }

    //服务器端监听

    if(listen(ser_sockfd, 5) < 0)

    {

        printf("Linsten Error!\n");

        return -1;

    }

 

    bzero(&cli_addr, sizeof(cli_addr));

    ser_len = sizeof(cli_addr);

 

    while(1)

    {

        printf("server_ftp>");

        //服务器端接受来自客户端的连接,返回一个套接字,此套接字为新建的一个,并将客户端的地址等信息存入cli_addr中

        //原来的套接字仍处于监听中

        if((cli_sockfd=accept(ser_sockfd, (SA *)&cli_addr, &cli_len)) < 0)

        {

            printf("Accept Error!\n");

            exit(1);

        }

        //由套接字接收数据时,套接字把接收的数据放在套接字缓冲区,再由用户程序把它们复制到用户缓冲区,然后由read函数读取

        //write函数同理

        if(read(cli_sockfd, commd, N) < 0)  //read函数从cli_sockfd中读取N个字节数据放入commd中

        {

            printf("Read Error!\n");

            exit(1);

        }

 

        printf("recvd [ %s ]\n",commd);

 

        if(strncmp(commd,"ls",2) == 0)

        {

            commd_ls(cli_sockfd);

        }else if(strncmp(commd,"get", 3) == 0 )

        {

            commd_get(cli_sockfd, commd+4);

        }else if(strncmp(commd, "put", 3) == 0)

        {

            commd_put(cli_sockfd, commd+4);

        }else

        {

            printf("Error!Command Error!\n");

        }

    }

 

    return 0;

}

 

void commd_ls(int sockfd)

{

    DIR * mydir =NULL;

    struct dirent *myitem = NULL;

    char commd[N] ;

    bzero(commd, N);

    //opendir为目录操作函数,类似于open函数

    //mydir中存有相关目录的信息(有待学习)

    if((mydir=opendir(".")) == NULL)

    {

        printf("OpenDir Error!\n");

        exit(1);

    }

 

    while((myitem = readdir(mydir)) != NULL)

    {

        if(sprintf(commd, myitem->d_name, N) < 0)

        {

            printf("Sprintf Error!\n");

            exit(1);

        }

 

        if(write(sockfd, commd, N) < 0 )

        {

            printf("Write Error!\n");

            exit(1);

        }

    }

 

    closedir(mydir);

    close(sockfd);

 

    return ;

}

 

void commd_get(int sockfd, char *filename)

{

    int fd, nbytes;

    char buffer[N];

    bzero(buffer, N);

 

    printf("get filename : [ %s ]\n",filename);

    if((fd=open(filename, O_RDONLY)) < 0)

    {

        printf("Open file Error!\n");

        buffer[0]='N';

        if(write(sockfd, buffer, N) <0)

        {

            printf("Write Error!At commd_get 1\n");

            exit(1);

        }

        return ;

    }

 

    buffer[0] = 'Y';    //此处标示出文件读取成功

    if(write(sockfd, buffer, N) <0)

    {

        printf("Write Error! At commd_get 2!\n");

        close(fd);

        exit(1);

    }

 

    while((nbytes=read(fd, buffer, N)) > 0)

    {

        if(write(sockfd, buffer, nbytes) < 0)

        {

            printf("Write Error! At commd_get 3!\n");

            close(fd);

            exit(1);

        }

    }

 

    close(fd);

    close(sockfd);

 

    return ;

}

 

void commd_put(int sockfd, char *filename)

{

    int fd, nbytes;

    char buffer[N];

    bzero(buffer, N);

 

    printf("get filename : [ %s ]\n",filename);

    if((fd=open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0)

    {

        printf("Open file Error!\n");

        return ;

    }

 

    while((nbytes=read(sockfd, buffer, N)) > 0)

    {

        if(write(fd, buffer, nbytes) < 0)

        {

            printf("Write Error! At commd_put 1!\n");

            close(fd);

            exit(1);

        }

    }

 

    close(fd);

    close(sockfd);

 

    return ;

}


--------------------- 



标签: 服务器搭建
分享:
评论:
你还没有登录,请先