Implementing Baidu Netdisk in C language under Linux system (with implementation steps and full code explanation)

Implementing Baidu Netdisk in C language under Linux system

Write a network disk in C language under Linux operating system

This experiment is completedComplete network disk functions (query files, download files, upload files, refresh the interface, and exit the system) ,Including additional functions (Query files in a specific directory for downloading or uploading).

  • Initial file allocation, the initial files in the root directory are dd.txt ee.txt and the files in ./download are a.txt b.txt c.txt. . Used for customer downloads and customer upload files respectively.

Insert image description here
Insert image description here

  • Refresh the network disk interface: When the user enters 4, re-enter the visual interface of the network disk and allow the user to choose the operation to be performed.

Insert image description here

void net_disk_ui()   //网盘可视化页面
{
    
    
    printf("======================TCP网盘客户端==================\n");
    printf("=========================功能菜单====================\n");
    printf("\t\t\t1.查询文件\n");
    printf("\t\t\t2.下载文件\n");
    printf("\t\t\t3.上传文件\n");
    printf("\t\t\t4.刷新界面\n");
    printf("\t\t\t0.退出系统\n");
    printf("------------------------------------------------------\n");
    printf("请选择你要执行的操作: \n");
}
case '4':
{
    
    
    net_disk_ui();
}
  • Query files: When the user enters 1, output the file list in the home/drj/ directory

Insert image description here

case '1':   //  要让服务器给我们发送目录信息->客户端也要创捷线程
    // 这个while循环本身也是死循环,我们要让客户端也创建线程,让接受服务器的数据的代码放进线程中
    send_msg.type = MSG_TYPE_FILENAME;
    res = write(client_socket, &send_msg, sizeof(MSG));
    if (res < 0)
    {
    
    
        perror("send msg error: ");
    }
    memset(&send_msg, 0, sizeof(MSG));
    break;
  • Download files: According to the given path of the downloaded file and the specified location to be downloaded, download two files continuously, and the download path and content are correct.
    • When the user enters 2, first displays the content in the current directory /home/drj, allowing the user to choose which one to download. a file
    • After downloading, the ./download directory contains two files: dd.txt and ee.txt. After checking the file contents, the download was successful.

Insert image description here

// 客户端
case '2':
{
    
    
    send_msg.type = MSG_TYPE_DONWLOAD;
    struct dirent* dir = NULL;
    printf("there are  files in /home/drj : \n");
    DIR* dp = opendir("/home/drj");
    while (1)
    {
    
    
        dir = readdir(dp);
        if (NULL == dir)
        {
    
    
            break;
        }
        if (dir->d_name[0] != '.')
            printf("%s  ", dir->d_name);
    }
    printf("\ninput download filename: \n");
    scanf("%s", down_file_name);
    strcpy(send_msg.fname, down_file_name);
    res = write(client_socket, &send_msg, sizeof(MSG));
    if (res < 0)
    {
    
    
        perror("send msg error: ");
    }
    memset(&send_msg, 0, sizeof(MSG));
    break;
}
// 服务器
else if (recv_msg.type == MSG_TYPE_DONWLOAD)
{
    
    
    strcpy(down_file_name, recv_msg.fname);
    printf("要下载的文件是%s\n", down_file_name);
    server_file_download(acpt_socket);
    memset(&recv_msg, 0, sizeof(MSG));
}
  • Upload files: Upload the downloaded files a.txt b.txt c.txt into the /home/drj directory. The transfer is completed and there are no errors on the server and client. And the number of bytes and content uploaded are correct.
    • Enter 3 to display the existing files in the current folder to the user and allow the user to select one to upload. Gives the path to the uploaded file and the current file size.
    • Upload three files in a row, and then check in the root directory whether the files are uploaded successfully and whether the article content is correct, etc. As you can see, all three files were uploaded successfully and the file contents are all correct.

Insert image description here

// 客户端
case '3': {
    
            
    send_msg.type = MSG_TYPE_UPLOAD;
    struct dirent* dir = NULL;
    printf("there are  files in ./download  : \n");
    DIR* dp = opendir("./download");
    while (1)
    {
    
    
        dir = readdir(dp);
        if (NULL == dir)
        {
    
    
            break;
        }
        if (dir->d_name[0] != '.')
            printf("%s  ", dir->d_name);
    }
    printf("\ninput upload filename: \n");
    scanf("%s", up_file_name);
    // 发送一个数据包告诉服务器,准备上传文件了
    strcpy(send_msg.fname, up_file_name);
    // f发送数据给服务器
    res = write(client_socket, &send_msg, sizeof(MSG));
    if (res < 0)
    {
    
    
        perror("send upload packege error");
        continue; //不走下面了
    }
    memset(&send_msg, 0, sizeof(MSG));
    // 由于考虑到上传文件是需要时间的,如果文件很大,那么就需要非常长的时间
    // 如果这个时候写在这里会导致其他功能卡住,因此需要把发送文件内容的代码放进线程里面,因此需要创建线程
    // 因此我们客户都拿还需要创建一个新的线程,专门处理文件的上传任务;
    pthread_create(&pthread_send_id, NULL, upload_file_thread, &client_socket); //创建一个线程
    break;
}

// 服务器
else if (recv_msg.type == MSG_TYPE_UPLOAD)  //如果收到的是上传包,说明准备接受客户端发来的文件数据
{
    
    
    printf("进入upload\n");

    //从数据包的文件名获取文件名信息并创建文件,默认创建的文件夹在家目录下
    strcpy(up_file_name, recv_msg.fname);

    char path[20] = "/home/drj/";
    strcat(path, up_file_name);
    printf("当前要下载到的文件位置是 %s \n", path);
    // 创建文件,在家目录下,下需要定义文件名描述符
    fd = open(path, O_CREAT | O_WRONLY, 0666);
    if (fd < 0)
    {
    
    
        perror("create up file error");
    }
}
else if (recv_msg.type == MSG_TYPE_UPLOAD_DATA)
{
    
    
    // 写的字节数是recv_msg.bytes
    printf("文件开始开始上传\n");
    res = write(fd, recv_msg.buffer, recv_msg.bytes);
    
    if (recv_msg.bytes < sizeof(recv_msg.buffer))
    {
    
    
        //说明是最后一个包,这部分数据是文件的最后数据了
        printf("client up file ok\n");
        close(fd);
    }
    memset(&recv_msg, 0, sizeof(MSG));
}

Complete code:

server

#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

char down_file_name[20] = {
    
     0 };
#define MSG_TYPE_LOGIN 0
#define MSG_TYPE_FILENAME 1
#define MSG_TYPE_DONWLOAD 2
#define MSG_TYPE_UPLOAD 3
#define MSG_TYPE_UPLOAD_DATA 4

typedef struct msg
{
    
    
    int type; // 协议类型  0 表示登录协议,1表示文件传输包 2 表示文件下载
    int flag; 
    char buffer[1024];  //存放除文件名之外的内容
    char fname[50];  //如果type是1 就是文件名传输包,这个结构体会添加新的字段;
    int bytes;   // 这个字段用来记录传输文件时候每个数据包实际的文件数
}MSG;//这个结构体会根据业务需求的不断变化,会添加新的字段。


void search_server_dir(int accept_socket)
// 通过打开服务器中的某个文件,并使用  socket 网络发送给客户端  至于什么文件我们先顶一个。。。e
//可以根据实际情况定义
{
    
    
    struct dirent * dir = NULL;   //定义目录的结构体;
    MSG info_msg = {
    
     0 };
    int res = 0;
    //opendir 是打开Linux目录的api函数
    DIR* dp = opendir("/home/drj");
    info_msg.type = MSG_TYPE_FILENAME;
    if (NULL == dp)
    {
    
    
        perror("open dir error: ");
        return;
    }
    while (1)
    {
    
    
        dir = readdir(dp);
        if (NULL == dir) //目录遍历完成,函数返回空值,表示目录全部读取完成
        {
    
    
            break;
        }
        if (dir->d_name[0] != '.') //过滤掉.隐藏文屏蔽 
        {
    
    
            printf("name = %s\n", dir->d_name);
            memset(info_msg.fname, 0, sizeof(info_msg.fname));
            strcpy(info_msg.fname, dir->d_name);
            res = write(accept_socket, &info_msg, sizeof(MSG)); //把每个文件名拷贝到
            // info_msg结构体中,通过该套接字发送出去。
            if (res < 0)
            {
    
    
                perror("send client error: ");
                return;
            }
        }
    }
}

void server_file_download(int accept_socket)
{
    
    
    MSG  file_msg = {
    
     0 };
    int res = 0;
    int fd;   //文件描述符  linux系统下很重要的概念,linux认为所有设备都是文件描述符。对文件的 打开对设备。
    // 都可以使用文件描述符概念。
    char path[20] = "/home/drj/";
    strcat(path, down_file_name);
    fd = open(path, O_RDONLY);

    if (fd < 0)
    {
    
    
        perror("file open error: ");
        return;
    }
    // 在读取文件并把文件传到客户端,这个时候msg结构体中的buffer 就是存放文件的内容,
    // 但是一般来说文件都超过1024,所以要发送多个包;
    file_msg.type = MSG_TYPE_DONWLOAD;
    strcpy(file_msg.fname, "ee.txt");

    while ((res = read(fd, file_msg.buffer, sizeof(file_msg.buffer))) > 0)
        // read用于读取文件的时候,当文件读到末尾的时  
        // res是实际读到的字节
    {
    
    
        file_msg.bytes = res;
        res = write(accept_socket, &file_msg, sizeof(MSG));
        if (res <= 0)
        {
    
    
            perror("server send file error: ");
        }
        memset(file_msg.buffer, 0, sizeof(file_msg.buffer));
    }

}

void* thread_fun(void* arg)
{
    
    
    int acpt_socket = *((int*)arg);
    int res;
    char buffer[50] = {
    
     0 };
    char up_file_name[20] = {
    
     0 };
    MSG recv_msg = {
    
     0 };
    int fd = -1;  //定义一个打开文件的描述符
    //read函数就是接受客户端发来的数据,返回实际从客户端那边收到的字节数。
    //buffer: 收到客户端数据后把数据存放的地址  sizeof(buffer) 就是希望读取的字节数
    //search_server_dir(acpt_socket);
    printf("目录发送客户端完成!\n");
    while (1)
    {
    
    
        // todo  #################################sizeof(recv_msg)
        res = read(acpt_socket, &recv_msg, sizeof(recv_msg));
        if (res == 0)  //说明客户端已经断开,read默认情况下他是堵塞模式,回答问题才能说出下一句话
        {
    
    
            printf("客户端已经断开");
            break;    // 线程结束
        }
        if (recv_msg.type == MSG_TYPE_FILENAME) //说明客户端发过来的是目录
        {
    
    
            search_server_dir(acpt_socket);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        else if (recv_msg.type == MSG_TYPE_DONWLOAD)
        {
    
    
            strcpy(down_file_name, recv_msg.fname);
            printf("要下载的文件是%s\n", down_file_name);
            server_file_download(acpt_socket);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        else if (recv_msg.type == MSG_TYPE_UPLOAD)  //如果收到的是上传包,说明准备接受客户端发来的文件数据
        {
    
    
            printf("进入upload\n");

            //从数据包的文件名获取文件名信息并创建文件,默认创建的文件夹在家目录下
            strcpy(up_file_name, recv_msg.fname);

            char path[20] = "/home/drj/";
            strcat(path, up_file_name);
            printf("当前要下载到的文件位置是 %s \n", path);
            // 创建文件,在家目录下,下需要定义文件名描述符
            fd = open(path, O_CREAT | O_WRONLY, 0666);
            if (fd < 0)
            {
    
    
                perror("create up file error");
            }
        }
        else if (recv_msg.type == MSG_TYPE_UPLOAD_DATA)
        {
    
    
            // 写的字节数是recv_msg.bytes
            printf("文件开始开始上传\n");
            res = write(fd, recv_msg.buffer, recv_msg.bytes);
            
            if (recv_msg.bytes < sizeof(recv_msg.buffer))
            {
    
    
                //说明是最后一个包,这部分数据是文件的最后数据了
                printf("client up file ok\n");
                close(fd);
            }
            memset(&recv_msg, 0, sizeof(MSG));
        }
        // printf("client read %s\n", buffer);
        // write(acpt_socket, buffer, res);
         memset(&recv_msg, 0, sizeof(MSG));
        //服务器收到客户端数据后,原封不动的发给客户端
    }
}
int main()
{
    
    
    char buffer[50] = {
    
     0 };
    int res = 0;
    int server_socket; //这个是socket网络描述符,也叫套接字描述符。
    int accept_socket;
    // 第一步:创建套接字描述符       --“买一部手机”
    pthread_t thread_id; //线程编号

    
    printf("开始创建tcp服务器\n");
    server_socket = socket(AF_INET, SOCK_STREAM, 0);//我们想要向网络发送数据都使用
    //server_socket这个套接字描述符

    if (server_socket < 0)
    {
    
    
        perror("socket create failed:");
        return 0;
    }

    // 第二步:要告诉这个服务器 我的ip地址和端口号 我们要有一个保存ip地址和端口的变量
                //          --“买电话卡”
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET; // 表示ipv4地址协议
    server_addr.sin_addr.s_addr = INADDR_ANY;   //inaddr_any 存服务器ip地址,告诉系统自动绑定网卡ip地址
    server_addr.sin_port = htons(1046);    //网络地址转换,把主机字节顺序转换成网络字节顺序
    // 端口号1024以上即可。
    // 
    // 
    // 如果服务器程序退出之后,又立刻打开服务器,系统会提示地址已经被使用
    //这是因为ip地址和端口号是系统资源,必须设置为端口号为重复使用。
    int optvalue = 1;
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optvalue, sizeof(optvalue));
    // 第三步:把我们设定好的ip地址和端口号绑定到我们的server_socket描述符上。 --“把电话卡插入手机上”

    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
    
    
        perror("server bind error:");
        return 0;
    }

    // 第四步:我们调用listen 开始监听程序    --“把电话放在身上,电话铃响听到声音”
    if (listen(server_socket, 10) < 0)
    {
    
    
        perror("server listen error:");
        return 0;
    }

    // 第五步:以上4个步骤都ok后,我们就可以等待客户端连接过来了。

    // accept 函数有一个特点,当我们程序调用这个函数的时候,如果没有客户端连接到我们的服务器,
    // 那么这个函数将堵塞(程序停下不走了),直到有客户端连接到服务器,这个函数将解开,并
    // 并且返回一个新的套接字描述符。那么后期和客户端的通讯都交给这个新的套接字描述符来负责。
    printf("TCP服务器准备完成,等待客户端连接!\n");
    
    while (1)
    {
    
    
        accept_socket = accept(server_socket, NULL, NULL);
		printf("有客户端连接到服务器!\n");
        //创建一个新的线程,创建成功之后,系统就会执行‘thread_fun’代码,这里就是多线程代码。
        pthread_create(&thread_id, NULL, thread_fun, &accept_socket);   // 第三个参数  函数指针 真正执行函数的指针
        // 移动到最前面函数里面去了。
    }

    printf("%s 向你问好!\n", "LINUX_C_SAMPLE");
    return 0;
}

client

#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>

// 编写客户端
#define MSG_TYPE_LOGIN 0
#define MSG_TYPE_FILENAME 1
#define MSG_TYPE_DONWLOAD 2
#define MSG_TYPE_UPLOAD 3
#define MSG_TYPE_UPLOAD_DATA 4
char down_file_name[20] = {
    
     0 };
char up_file_name[20] = {
    
     0 };
typedef struct msg
{
    
    
    int type; // 协议类型  0 表示登录协议,1表示文件传输包
    int flag;
    char buffer[1024]; //存放除文件名之外的内容
    char fname[50]; //如果type是1 就是文件名传输包,这个结构体会添加新的字段;
    int bytes; // 这个字段用来记录传输文件时候每个数据包实际的文件数
}MSG;//这个结构体会根据业务需求的不断变化,会添加新的字段。
  // 全局变量  用来打开文件进行读写的文件描述符,默认情况下为0
int fd = -1;//进行读写的文件标识符
void net_disk_ui()
{
    
    
    printf("======================TCP网盘客户端==================\n");
    printf("=========================功能菜单====================\n");
    printf("\t\t\t1.查询文件\n");
    printf("\t\t\t2.下载文件\n");
    printf("\t\t\t3.上传文件\n");
    printf("\t\t\t4.刷新界面\n");
    printf("\t\t\t0.退出系统\n");
    printf("------------------------------------------------------\n");
    printf("请选择你要执行的操作: \n");

}
// 根据网盘客户端业务需求,客户端想要查看下服务器这边目录下的文件信息。因此
// 服务器必须设计一个功能,把某个目录下的文件名信息全部获取出来发给客户端。
// 默认情况下服务器的目录,用户的目录设置为家home目录
// 在Linux下如何对文件和目录进行读取并获取文件名


void * thread_func(void* arg)
{
    
    
    int client_socket = *((int*)arg);
    MSG recv_msg = {
    
     0 };
    int res;
    char pwd[100] = {
    
     0 } ;
    while (1)
    {
    
    
        //用来接受服务器发过来的数据
        res = read(client_socket, &recv_msg, sizeof(MSG));
        if (recv_msg.type == MSG_TYPE_FILENAME)
        {
    
    
            printf("server path filename=%s\n", recv_msg.fname);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        else if (recv_msg.type == MSG_TYPE_DONWLOAD)  // 做好接受准备,一定是一个文件
        {
    
    

            // 1.创建一个目录
            if (mkdir("download", S_IRWXU) <0 )
            {
    
    
                if (errno == EEXIST)
                {
    
    
                    printf("download dir exist continue!!\n");
                }
                else
                {
    
    
                    perror("mkdir error: ");
                }
            }
            // 目录创建没有问题,就要开始创建文件了。
            if (fd == -1)  //表示文件还没打开过,若非0 已经打开过了
            {
    
    
                //printf("\ncurrent = %s\n", getcwd(NULL,0));
                char path[20] = "./download/";
                strcat(path, down_file_name);
                printf("download path = %s\n", path);
                fd = open(path, O_CREAT | O_WRONLY, 0666); //打开过肯定会有个文件描述返回  0666读写可执行
                if (fd < 0)
                {
    
    
                    perror("file open error: ");
                }

            }
            // 通过上面的创建目录以及文件描述的判断,通过后就可以从MSG结构体里面的buffer取数据了。
            // recv_msg.buffer  存放的就是文件的部分内容。 recv_msg.bytes就这个部分文件的字节。
            res = write(fd, recv_msg.buffer, recv_msg.bytes);
            if (res < 0)
            {
    
    
                perror("file write error : ");
            }
            // 那么我们判断文件的内容都全部发完了吗?通过recv_msg.bytes 如果小于recv_buffer的1024 
            if (recv_msg.bytes < sizeof(recv_msg.buffer))
            {
    
    
                printf("file download finish!!\n");
                close(fd);
                fd = -1;
            }
        }

    }
}

void* upload_file_thread(void * args)
{
    
    
    // 客户端实现上传文件到服务器逻辑
    // 1.打开文件 
    MSG up_file_msg = {
    
     0 };
    int client_socket = *((int*)args);
    int fd = -1;
    int res = 0;  //实际读入的文件名
    char buffer[1024] = {
    
     0 }; //用来保存读取文件的缓冲区数据


    char path[20] = "./download/";
    strcat(path, up_file_name);
    printf("客户端上传文件的路径是%s \n", path);
    fd = open(path, O_RDONLY);
    if (fd < 0)
    {
    
    
        perror("client  open up file error:");
        return NULL;
    }
    up_file_msg.type = MSG_TYPE_UPLOAD_DATA;
    //2.读取文件
    while ((res = read(fd, buffer, sizeof(buffer)) )> 0)
    {
    
    
        // 要把文件数据拷贝到MSG结构体中的buffer中
        printf("传入的字节数目:%d 字节\n", res);
        memcpy(up_file_msg.buffer, buffer, res);
        up_file_msg.bytes = res;
        res = write(client_socket, &up_file_msg, sizeof(MSG));//写的字节数一定是读的总数据
        memset(buffer, 0, sizeof(buffer));
        memset(up_file_msg.buffer, 0, sizeof(up_file_msg.buffer));
    }
}


int main()
{
    
    
    int client_socket;
    //todo 定义
    pthread_t  pthread_id;  //线程编号
    pthread_t  pthread_send_id;
    char c;
    struct sockaddr_in server_addr; //用来连接到服务器的ip地址和端口号
    char buffer[50] = {
    
     0 };
    client_socket = socket(AF_INET,SOCK_STREAM,0);
    int res;
    MSG recv_msg = {
    
     0 };
    MSG send_msg = {
    
     0 };
    if (client_socket < 0)
    {
    
    
        perror("client socket faile: ");
        return 0;
    }
    server_addr.sin_family = AF_INET; //ipv协议 且自动匹配绑定 
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    // 两种方法如果服务器和客户端都在同一台电脑中,ip地址可以设置为127.0.0.1
    // 现在就是服务器和客户端中在同一个机子上,因此可以127.0.0.1.
    server_addr.sin_port = htons(1046);
    printf("这是客户端\n");
    // 创建好套接字之后,客户端要连接到服务器,使用conect()函数

    if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
    
    
        perror("connect error:  ");
        return 0;
    }
    printf("客户端连接服务器成功\n");
    
    pthread_create(&pthread_id, NULL, thread_func, &client_socket);
    net_disk_ui();
    // 我们用户在客户端中连续输入字符,回车表示把数据发出去,把buffer里的数据发出去;服务器有固定ip地址即可,不一定在一个主机上
    while (1)
    {
    
    
        c = getchar();
        switch (c)
        {
    
    
        case '1':   //  要让服务器给我们发送目录信息->客户端也要创捷线程
            // 这个while循环本身也是死循环,我们要让客户端也创建线程,让接受服务器的数据的代码放进线程中
            send_msg.type = MSG_TYPE_FILENAME;
            res = write(client_socket, &send_msg, sizeof(MSG));
            if (res < 0)
            {
    
    
                perror("send msg error: ");
            }
            memset(&send_msg, 0, sizeof(MSG));
            break;
        case '2':
        {
    
    
            send_msg.type = MSG_TYPE_DONWLOAD;
            struct dirent* dir = NULL;
            printf("there are  files in /home/drj : \n");
            DIR* dp = opendir("/home/drj");
            while (1)
            {
    
    
                dir = readdir(dp);
                if (NULL == dir)
                {
    
    
                    break;
                }
                if (dir->d_name[0] != '.')
                    printf("%s  ", dir->d_name);
            }
            printf("\ninput download filename: \n");
            scanf("%s", down_file_name);
            strcpy(send_msg.fname, down_file_name);
            res = write(client_socket, &send_msg, sizeof(MSG));
            if (res < 0)
            {
    
    
                perror("send msg error: ");
            }
            memset(&send_msg, 0, sizeof(MSG));
            break;
        }
        case '3': {
    
            
            send_msg.type = MSG_TYPE_UPLOAD;
            struct dirent* dir = NULL;
            printf("there are  files in ./download  : \n");
            DIR* dp = opendir("./download");
            while (1)
            {
    
    
                dir = readdir(dp);
                if (NULL == dir)
                {
    
    
                    break;
                }
                if (dir->d_name[0] != '.')
                    printf("%s  ", dir->d_name);
            }
            printf("\ninput upload filename: \n");
            scanf("%s", up_file_name);
            // 发送一个数据包告诉服务器,准备上传文件了
            strcpy(send_msg.fname, up_file_name);
            // f发送数据给服务器
            res = write(client_socket, &send_msg, sizeof(MSG));
            if (res < 0)
            {
    
    
                perror("send upload packege error");
                continue; //不走下面了
            }
            memset(&send_msg, 0, sizeof(MSG));
            // 由于考虑到上传文件是需要时间的,如果文件很大,那么就需要非常长的时间
            // 如果这个时候写在这里会导致其他功能卡住,因此需要把发送文件内容的代码放进线程里面,因此需要创建线程
            // 因此我们客户都拿还需要创建一个新的线程,专门处理文件的上传任务;
            pthread_create(&pthread_send_id, NULL, upload_file_thread, &client_socket); //创建一个线程
            break;
        }
        case '4':
        {
    
    
            net_disk_ui();
        }
        }
    }
    /*
    while (1)
    {
 
        res = read(client_socket, &recv_msg, sizeof(MSG));


        if (recv_msg.type == MSG_TYPE_FILENAME)
        {
            printf("server path filename = %s\n", recv_msg.fname);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        
    }
    */


    /*
    //用户在客户端中连续输入字符,回车发送数据
    while (fgets(buffer, sizeof(buffer), stdin) != NULL)
    {
        res = write(client_socket, buffer, sizeof(buffer));
        printf("send bytes =%d\n", res);
        memset(buffer, 0, sizeof(buffer));

        res = read(client_socket, buffer, sizeof(buffer));
        printf("recv from server info : % s\n", buffer);
        memset(buffer, 0, sizeof(buffer));
    }
    */


    printf("%s 向你问好!\n", "linux_02");
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_63669388/article/details/133491678