使用TCP客户端下载TCP服务器所在目录下的文件的功能(TCP实现文件传输和下载)

流程:    

        客户端给服务器发送要下载的文件名

        服务器收到文件名之后,判断当前路径下有没有该文件

        //open(O_RDONLY) 如果报错 且错误码为 ENOENT 说明文件不存在

        如果不存在,服务器给客户端发送文件不存在的消息

        如果存在,服务器也要先发送文件存在的消息给客户端

        然后循环读取文件内存,发送给客户端

客户端接到服务器的应答后,

如果文件不存在,则重新发送文件名给服务器

如果存在,open(O_WRONLY|O_CREAT|O_TRUNC,0664)

循环读取文件内容并写入文件

注意:服务器程序和客户端程序不要运行在同一个路径下。

运行结果图:

服务器端

客户端

代码如下:

service.c (head.h为自定义的头文件,在文末有)

#include <head.h>
typedef struct _MSG
{
    int len;
    char file_buff[128];
} msg_t;
int main(int argc, const char *argv[])
{
    if (3 != argc)
    {
        printf("usage error:./a.out <ip> <port>...\n");
        exit(-1);
    }
    // 创建套接字
    int sockfd;
    msg_t msg;
    if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        PRINT_ERR("socket error");
    }
    // 填充服务器网络信息结构体
    struct sockaddr_in serveraddr;
    socklen_t serveraddr_len = sizeof(serveraddr);
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    // 绑定
    if (-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len))
    {
        PRINT_ERR("bind error");
    }
    // 监听
    if (-1 == listen(sockfd, 3))
    {
        PRINT_ERR("listen error");
    }
    int acceptfd=0;
    int fd;
    int nbytes;
    char file_name[32] = {0};
    char buff[128] = {0};
    struct sockaddr_in clientaddr;
    socklen_t clientaddr_len = sizeof(clientaddr);
    while (1)
    {
        memset(file_name, 0, sizeof(file_name));
        printf("正在等待客户端连接...\n");
        // 等待连接
        if (-1 == (acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len)))
        {
            PRINT_ERR("accept error");
        }
        // 收发数据
        printf("客户端[%s:%d]连接成功...\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
        // while (1)
        // {
        RENAME:
            if (-1 == (nbytes = recv(acceptfd, file_name, sizeof(file_name), 0)))
            {
                PRINT_ERR("recv001 error");
            }
            else if (nbytes == 0)
            {
                printf("客户端[%s:%d]断开了连接...\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
               continue;
            }
            printf("客户端[%s:%d]要下载的文件为[%s]...\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), file_name);
            if (-1 == (fd = open(file_name, O_RDONLY)))
            {
                if (errno == ENOENT)
                {
                    printf("客户端[%s:%d]要下载的文件[%s]不存在...\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), file_name);
                    strcpy(buff, "file_no_exit");
                    if (-1 == send(acceptfd, buff, sizeof(buff), 0))
                    {
                        PRINT_ERR("send error");
                    }
                    goto RENAME;
                }
                else
                {
                    PRINT_ERR("open error");
                }
            }
            else
            {
                strcpy(buff, "file_exit");
                if (-1 == send(acceptfd, buff, sizeof(buff), 0))
                {
                    PRINT_ERR("send error");
                }
                memset(&msg, 0, sizeof(msg));
                nbytes=0;
                while (0 < (nbytes = read(fd, msg.file_buff, sizeof(msg.file_buff))))
                {
                    msg.len = nbytes;
                    if (-1 == send(acceptfd, &msg, sizeof(msg), 0))
                    {
                        PRINT_ERR("send error");
                    }
                    memset(&msg, 0, sizeof(msg));
                    // }
                }
                msg.len = 0;
                if (-1 == send(acceptfd, &msg, sizeof(msg), 0))
                {
                    PRINT_ERR("send error");
                }
            }

            close(fd);
            close(acceptfd);
        }
    // }
    close(sockfd);
    return 0;
}

client.c

#include <head.h>
typedef struct _MSG
{
    int len;
    char file_buff[128];
} msg_t;
int main(int argc, const char *argv[])
{
    // 入参合理性检查
    if (3 != argc)
    {
        printf("usage error:%s <ip> <port>", argv[0]);
        exit(-1);
    }
    // 创建套接字
    int sockfd;
    msg_t msg;
    char file_name[32] = {0};
    char buff[128] = {0};
    int nbytes = 0;
    int fd;
    if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        PRINT_ERR("socket error");
    }
    // 填充服务器网络信息结构体
    struct sockaddr_in serveraddr;
    socklen_t serveraddr_len = sizeof(serveraddr);
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));
    //
    if (-1 == connect(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len))
    {
        PRINT_ERR("connect error");
    }
    printf("与服务器连接成功...\n");
    while (1)
    {
    RENAME:
        printf("请输入您要下载的文件名称(quit 退出):");
        fgets(file_name, sizeof(file_name), stdin);
        file_name[strlen(file_name) - 1] = '\0';
        if (strcmp(file_name, "quit") == 0)
        {
            printf("您主动断开了连接,程序已退出...\n");
            break;
        }
        if (-1 == send(sockfd, file_name, sizeof(file_name), 0))
        {
            PRINT_ERR("send error");
        }

        if (-1 == recv(sockfd, buff, sizeof(buff), 0))
        {
            PRINT_ERR("recv error");
        }
        if (strcmp(buff, "file_no_exit") == 0)
        {
            printf("您要下载的文件[%s]不存在...\n", file_name);
            goto RENAME;
            // break;
        }
        else if ((strcmp(buff, "file_exit") == 0))
        {
            printf("文件[%s]存在,开始下载...\n", file_name);

            if (-1 == (fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0664)))
            {
                PRINT_ERR("open error");
            }
            while (1)
            {
                memset(&msg, 0, sizeof(msg));
                if (-1 == (nbytes = recv(sockfd, &msg, sizeof(msg), 0)))
                {
                    PRINT_ERR("recv error");
                }
                if (msg.len == 0)
                {
                    break;
                }
                write(fd, msg.file_buff, msg.len);
            }
            printf("文件[%s]下载完成,程序退出...\n", file_name);
            break;
            close(fd);
        }
    }
    close(sockfd);
    return 0;
}

head.h(只使用需要的头文件即可,下面包含的有其他项目的头文件)

#ifndef __HEAD_H__
#define __HEAD_H__

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h> //opendir closedir readdir函数头文件
#include <sys/wait.h>
#include <pthread.h>   //创建线程
#include <semaphore.h> //无名信号量
#include <signal.h>
#include <sys/ipc.h> //IPC进程间通信键的获取
#include <sys/msg.h> //IPC消息队列
#include <sys/shm.h> //IPC共享内存
#include <sys/sem.h> //IPC信号灯集
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h> // inet_addr 将点分十进制的字符串 转换成  网络字节序的 无符号四字节整型
#define PRINT_ERR(errmsg) \
    do                    \
    {                     \
        perror(errmsg);   \
        return -1;        \
    } while (0)

#endif

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值