TCP实现FTP功能

服务端server.c

#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//list:打开当前目录,循环读,判断是否是隐藏文件,是否是普通文件,是则发送文件名
void list(int acceptfd, char *buf, int size)
{
    struct dirent *file = NULL;
    struct stat st;
    //打开当前目录
    DIR *dir = opendir(".");
    //循环读当前目录
    while ((file = readdir(dir)) != NULL)
    {
        //获取读到文件的属性
        stat(file->d_name, &st);
        //判断是不是隐藏文件
        if (file->d_name[0] == '.')
            continue;
        //判断是不是普通文件
        if (S_ISREG(st.st_mode))
        {
            //把文件名发送给客户端
            send(acceptfd, file->d_name, size, 0);
        }
    }
    //发送结束标志
    strcpy(buf, "LISTOK");
    send(acceptfd, buf, size, 0);
    closedir(dir);
}
//读打开文件,发送给客户端
void get(int acceptfd, char *buf, int size)
{
    //只读打开文件
    int fd = open(buf + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open err.");
        return;
    }
    int ret;
    //循环读取文件内容
    while (ret = read(fd, buf, size - 1))//为buf补结束标志'\0'
    {
        buf[ret] = '\0';
        send(acceptfd, buf, size, 0);//发送读到的数据(包含'\0')
    }
    //发送结束标志
    strcpy(buf, "send ok");
    send(acceptfd, buf, size, 0);
    close(fd);
}
//打开或新建文件,循环收并写入文件
void put(int acceptfd, char *buf, int size)
{
    //只写,存在清空,不存在创建打开文件
    int fd = open(buf + 4, O_WRONLY | O_TRUNC | O_CREAT, 0666);
    if (fd < 0)
    {
        perror("open err.");
        return;
    }
    //接收并写入
    while (1)
    {
        //读取客户端发送的消息
        if (recv(acceptfd, buf, size, 0) < 0)
        {
            perror("recv err.");
            return;
        }
        //判断结束标志
        if (strncmp(buf, "PUTOK", 5) == 0)
            break;
        //写实际读到的内容
        write(fd, buf, strlen(buf));
    }
    close(fd);
}
int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("please input %s <ip> <port>\n", argv[0]);
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err.");
        return -1;
    }
    //填充相应结构体
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");

    socklen_t len = sizeof(caddr);
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err.");
        return -1;
    }
    if (listen(sockfd, 5) < 0)
    {
        perror("listen err.");
        return -1;
    }
    while (1)
    {

        int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err.");
            return -1;
        }
        printf("client: ip=%s port=%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
        char buf[128] = "0";
        int ret = 0;
        while (1)
        {
            ret = recv(acceptfd, buf, sizeof(buf), 0);
            if (ret < 0)
            {
                perror("recv err.");
                return -1;
            }
            else if (ret == 0)
            {
                printf("client exit.\n");
                break;
            }
            else
            {
                if (strncmp(buf, "list", 4) == 0)
                {
                    list(acceptfd, buf, sizeof(buf));
                }
                else if (strncmp(buf, "get ", 4) == 0)
                {
                    get(acceptfd, buf, sizeof(buf));
                }
                if (strncmp(buf, "put ", 4) == 0)
                {
                    put(acceptfd, buf, sizeof(buf));
                }
            }
        }
        close(acceptfd);
    }
    close(sockfd);
    return 0;
}

客户端client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
void show(void)
{
    printf("-----------------list-------------------\n");
    printf("-----------------put filename-----------\n");
    printf("-----------------get filename-----------\n");
    printf("-----------------quit-------------------\n");
}
//从服务端接受文件名并打印
void list(int sockfd, char *buf, int size)
{
    int ret = 0;
    while (1)
    {
        //循环接收
        ret = recv(sockfd, buf, size, 0);
        if (ret < 0)
        {
            perror("recv err.");
            return;
        }
        //判断是不是结束标志
        if (strncmp(buf, "LISTOK", 6) == 0)
            break;
        printf("%s\n", buf);
    }
}
//打开文件,循环读取写入文件
void get(int sockfd, char *buf, int size)
{
    //只写,存在清空,不存在创建打开文件
    int fd = open(buf + 4, O_WRONLY | O_TRUNC | O_CREAT, 0666);
    if (fd < 0)
    {
        perror("open err.");
        return ;
    }
    while (1)
    {
        //读取服务端发送的数据
        if (recv(sockfd, buf, size, 0) < 0)
        {
            perror("recv err.");
            return;
        }
        //判断结束标志
        if (strncmp(buf, "send ok", 7) == 0)
            break;
        //写实际读到的个数
        write(fd, buf, strlen(buf));
    }
    close(fd);
}
//读打开文件,然后循环发送给服务端
void put(int sockfd, char *buf, int size)
{
    //只读打开文件
    int fd = open(buf + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open err.");
        return;
    }
    //循环读 发送
    int ret = 0;
    //循环读文件
    while (ret = read(fd, buf, size - 1))//为buf补'\0',所以-1为'\0'留位置
    {
        buf[ret] = '\0';
        //发送读到的数据
        send(sockfd, buf, size, 0);
    }
    //发送结束标志
    strcpy(buf, "PUTOK");
    send(sockfd, buf, size, 0);
    close(fd);
}
int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("please input %s <ip> <port>\n", argv[0]);
        return -1;
    }
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err.");
        return -1;
    }
    //填充相应结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[2]));
    saddr.sin_addr.s_addr = inet_addr(argv[1]);
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err.");
        return -1;
    }
    char buf[128] = "0";
    while (1)
    {
        show();
        printf("请输入命令:");
        fgets(buf, sizeof(buf), stdin);
        if (buf[strlen(buf) - 1] == '\n')
            buf[strlen(buf) - 1] = '\0';

        send(sockfd, buf, sizeof(buf), 0);

        if (strncmp(buf, "list", 4) == 0)
        {
            list(sockfd, buf, sizeof(buf));
        }
        else if (strncmp(buf, "get ", 4) == 0)
        {
            get(sockfd, buf, sizeof(buf));
        }
        else if (strncmp(buf, "put ", 4) == 0)
        {
            put(sockfd, buf, sizeof(buf));
        }
        else if (strncmp(buf, "quit", 4) == 0)
        {
            break;
        }
    }
    close(sockfd);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值