TCP实现FTP功能

文件传输协议(File Transfer Protocol,FTP)是一种在网络中进行文件传输的广泛使用的标准协议。作为网络通信中的基础工具,FTP允许用户通过客户端软件与服务器进行交互,实现文件的上传、下载和其他文件操作。FTP工作在OSI模型的应用层,通常使用TCP作为其传输协议,确保数据传输的可靠性和顺序性。

项目要求

有服务器和客户端代码,基于TCP写的。

在同一路径下,将客户端可执行代码复制到其他的路径下,接下来在不同的路径下运行服务器和客户端。相当于另外一台电脑在访问服务器。

客户端和服务器链接成功后出现以下提示:四个功能

***************list**************//列出服务器所在目录下的普通文件名

***********put filename**********//从客户端所在路径上传文件

***********get filename**********//从服务器所在路径下载文件

**************quit***************//退出(可只退出客户端,服务器等待下一个客户端链接)

初版服务器

TCP实现FTP功能_第1张图片

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
char str[32];
char buf[128];
int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("usage:%s <端口号>\n", argv[0]);
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);

    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = ntohs(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    int len = sizeof(caddr);

    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");

    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");

    while (1)
    {
        int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("port:%d ip:%s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));
        printf("accpetfd:%d\n", acceptfd);

        while (1)
        {
            int ret;
            ret = recv(acceptfd, str, sizeof(str), 0);
            printf("来自客户端命令:%s\n", str);
            memset(buf, 0, sizeof(buf));
            if (ret < 0)
            {
                perror("recv err");
                return -1;
            }
            else if (ret == 0)
            {
                printf("client exit\n");
                break;
            }
            else
            {
                if (!strcmp(str, "list"))
                {
                    // 打开目录文件
                    DIR *dir;
                    dir = opendir(".");
                    struct dirent *d;
                    if (NULL == dir)
                    {
                        perror("opendir err");
                        return -1;
                    }
                    // 循环读目录
                    while ((d = readdir(dir)) != NULL)
                    {
                        // 判断是否为普通文件
                        if (d->d_type == 8)
                            // 发送给客户端
                            send(acceptfd, d->d_name, 128, 0);
                    }
                    // 发送一个结束的标志
                    send(acceptfd, "list end", 128, 0);
                    closedir(dir);
                }
                else if (!strncmp(str, "put ", strlen("put ")))
                {
                    int fd = open(str + 4, O_WRONLY | O_CREAT | O_TRUNC, 0777);
                    if (fd < 0)
                    {
                        perror("open err");
                        return -1;
                    }
                    // 接受客户端传来的文件内容
                    while (1)
                    {
                        ret = recv(acceptfd, buf, sizeof(buf), 0);
                        if (!strcmp(buf, "put end"))
                        {
                            printf("%s\n", buf);
                            break;
                        }
                        if (ret < 0)
                        {
                            perror("recv err");
                            return -1;
                        }
                        else if (ret == 0)
                        {
                            printf("client exit\n");
                            break;
                        }
                        // 写到目标文件里面
                        write(fd, buf, strlen(buf));
                        memset(buf, 0, sizeof(buf));
                    }
                    close(fd);
                }
                else if (!strncmp(str, "get ", strlen("get ")))
                {
                    int fd = open(str + 4, O_RDONLY);
                    if (fd < 0)
                    {
                        perror("open err");
                        return -1;
                    }
                    // 循环读文件
                    while ((read(fd, buf, sizeof(buf))) != 0)
                    {
                        // 发送给服务器
                        send(acceptfd, buf, sizeof(buf), 0);
                        memset(buf, 0, sizeof(buf));
                    }
                    send(acceptfd, "get end", 8, 0);
                    memset(buf, 0, sizeof(buf));
                    printf("get file success\n");
                    close(fd);
                }
            }
            memset(buf, 0, sizeof(buf));
        }
        close(acceptfd);
    }
    close(sockfd);
    return 0;
}

初版客户端

TCP实现FTP功能_第2张图片

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
char str[32];
char buf[128];
void help()
{
    printf("********************************************\n");
    printf("*                 功能菜单                 *\n");
    printf("********************************************\n");
    printf("*   list:列出服务器所在目录下的普通文件名  *\n");
    printf("*   put filename:从客户端所在路径上传文件  *\n");
    printf("*   get filename:从服务器所在路径下载文件  *\n");
    printf("*   quit:退出                              *\n");
    printf("********************************************\n");
}
int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("usage:%s  <端口号>\n", argv[0]);
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);

    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;                 // IPV4
    saddr.sin_port = htons(atoi(argv[2]));      // 端口号
    saddr.sin_addr.s_addr = inet_addr(argv[1]); // 虚拟机IP地址

    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err");
        return -1;
    }
    printf("connect ok\n");

    help();

    while (1)
    {
        fgets(str, sizeof(str), stdin);
        if (str[strlen(str) - 1] == '\n')
            str[strlen(str) - 1] = '\0';
        send(sockfd, str, sizeof(str), 0);
        memset(buf, 0, sizeof(buf));
        if (!strncmp(str, "list", strlen("list")))
        {
            while (1)
            {
                // 接收服务器目录信息
                recv(sockfd, buf, sizeof(buf), 0);
                printf("%s\t", buf);
                if (!strcmp(buf, "list end"))
                    break;
            }
            printf("\n");
        }
        else if (!strncmp(str, "put ", strlen("put ")))
        {
            int fd = open(str + 4, O_RDONLY);
            if (fd < 0)
            {
                perror("open err");
                return -1;
            }
            // 循环读文件
            while (read(fd, buf, sizeof(buf)) != 0)
            {
                // 发送给服务器
                send(sockfd, buf, sizeof(buf), 0);
                memset(buf, 0, sizeof(buf));
            }
            send(sockfd, "put end", 8, 0);
            memset(buf, 0, sizeof(buf));
            printf("put file success\n");
            close(fd);
        }
        else if (!strncmp(str, "get ", strlen("get ")))
        {
            int fd = open(str + 4, O_WRONLY | O_CREAT | O_TRUNC, 0777);
            if (fd < 0)
            {
                perror("open err");
                return -1;
            }
            // 接受服务器传来的文件内容
            while (1)
            {
                recv(sockfd, buf, sizeof(buf), 0);
                if (!strcmp(buf, "get end"))
                {
                    printf("%s\n", buf);
                    break;
                }
                else
                {
                    // 写到目标文件里面
                    write(fd, buf, strlen(buf));
                    memset(buf, 0, sizeof(buf));
                }
            }
            close(fd);
        }
        else if (!strcmp(str, "quit"))
            break;
    }

    close(sockfd);
    return 0;
}

终极版本

 服务器

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
char str[32];
char buf[128];
int ret;
int list_file(int acceptfd)
{
    DIR *dir;
    dir = opendir(".");
    struct dirent *d;
    if (NULL == dir)
    {
        perror("opendir err");
        return -1;
    }
    while ((d = readdir(dir)) != NULL)
    {
        if (d->d_type == 8)
        {
            send(acceptfd, d->d_name, 128, 0);
        }
    }
    closedir(dir);
    send(acceptfd, "list end", 128, 0);
}

int put_file(int acceptfd, char *str)
{
    int fd = open(str + 4, O_WRONLY | O_CREAT | O_TRUNC, 0777);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    while (1)
    {
        ret = recv(acceptfd, buf, sizeof(buf), 0);
        if (!strcmp(buf, "put end"))
        {
            printf("%s\n", buf);
            break;
        }
        if (ret < 0)
        {
            perror("recv err");
            return -1;
        }
        else if (ret == 0)
        {
            printf("client exit\n");
            break;
        }
        write(fd, buf, strlen(buf));
    }
    close(fd);
}

int get_file(int acceptfd, char *str)
{
    int fd = open(str + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    while ((read(fd, buf, sizeof(buf))) != 0)
    {
        send(acceptfd, buf, sizeof(buf), 0);
        memset(buf, 0, sizeof(buf));
    }
    send(acceptfd, "get end", 128, 0);
    printf("get file success\n");
    close(fd);
}

int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("usage:%s <端口号>\n", argv[0]);
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);

    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = ntohs(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    int len = sizeof(caddr);

    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");

    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");

    while (1)
    {
        int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("port:%d ip:%s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));
        printf("accpetfd:%d\n", acceptfd);

        while (1)
        {
            ret = recv(acceptfd, str, sizeof(str), 0);
            printf("来自客户端命令:%s\n", str);
            memset(buf, 0, sizeof(buf));
            if (ret < 0)
            {
                perror("recv err");
                return -1;
            }
            else if (ret == 0)
            {
                printf("client exit\n");
                break;
            }
            else
            {
                if (!strncmp(str, "list", strlen("list")))
                    list_file(acceptfd);
                else if (!strncmp(str, "put ", strlen("put ")))
                    put_file(acceptfd, str);
                else if (!strncmp(str, "get ", strlen("get ")))
                    get_file(acceptfd, str);
                memset(buf, 0, sizeof(buf));
            }
        }
        close(acceptfd);
    }
    close(sockfd);
    return 0;
}

 客户端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
char str[32];
char buf[128];
void help()
{
    printf("********************************************\n");
    printf("*                 功能菜单                 *\n");
    printf("********************************************\n");
    printf("*   list:列出服务器所在目录下的普通文件名  *\n");
    printf("*   put filename:从客户端所在路径上传文件  *\n");
    printf("*   get filename:从服务器所在路径下载文件  *\n");
    printf("*   quit:退出                              *\n");
    printf("********************************************\n");
}

int list_file(int sockfd)
{
    while (1)
    {
        recv(sockfd, buf, sizeof(buf), 0);
        if (!strcmp(buf, "list end"))
        {
            printf("\n");
            printf("%s\n", buf);
            break;
        }
        else
        {
            printf("%s\t", buf);
        }
    }
}

int put_file(int sockfd, char *str)
{
    int fd = open(str + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    while (read(fd, buf, sizeof(buf)) != 0)
    {
        send(sockfd, buf, sizeof(buf), 0);
        memset(buf, 0, sizeof(buf));
    }
    send(sockfd, "put end", 128, 0);
    printf("put file success\n");
    close(fd);
}

int get_file(int sockfd, char *str)
{
    int fd = open(str + 4, O_WRONLY | O_CREAT | O_TRUNC, 0777);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    while (1)
    {
        recv(sockfd, buf, sizeof(buf), 0);
        if (!strcmp(buf, "get end"))
        {
            printf("%s\n", buf);
            break;
        }
        else
        {
            // printf("%s", buf);
            write(fd, buf, strlen(buf));
        }
    }
    close(fd);
}
int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("usage:%s  <端口号>\n", argv[0]);
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);

    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;                 // IPV4
    saddr.sin_port = htons(atoi(argv[2]));      // 端口号
    saddr.sin_addr.s_addr = inet_addr(argv[1]); // 虚拟机IP地址

    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err");
        return -1;
    }
    printf("connect ok\n");

    help();

    while (1)
    {
        fgets(str, sizeof(str), stdin);
        if (str[strlen(str) - 1] == '\n')
            str[strlen(str) - 1] = '\0';
        send(sockfd, str, sizeof(str), 0);
        memset(buf, 0, sizeof(buf));
        if (!strncmp(str, "list", strlen("list")))
            list_file(sockfd);
        else if (!strncmp(str, "put ", strlen("put ")))
            put_file(sockfd, str);
        else if (!strncmp(str, "get ", strlen("get ")))
            get_file(sockfd, str);
        else if (!strcmp(str, "quit"))
            break;
    }

    close(sockfd);
    return 0;
}

你可能感兴趣的:(tcp/ip,linux,c语言,网络,网络协议)