一.项目课题 <基于TCP的文件传输协议实现>

客户端代码

需要cJSON.c文件和cJSON.h文件

c 复制代码
在这里插入代码片

#include "myheadth.h"
#include "myfun.h"

#define TIME 10
int sockfd;
void heartbeat(int signum)
{
    cJSON* root = cJSON_CreateObject();
    cJSON_AddStringToObject(root,"request","heartbeat");        
    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd,JSstr1,strlen(JSstr1),0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;

    alarm(TIME);
}

int main(int argc,char **argv)
{
    if(argc < 3)
    {
        fprintf(stderr,"Usage <%s SERIP SERPOST>\n",argv[0]);
        return -1;
    }

    /* 1. 创建套接字*/
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket");
        return -1;
    }

    /* 2.连接服务器*/
    sin_t server = {AF_INET};
    server.sin_port = htons(atoi(argv[2]));
    server.sin_addr.s_addr = inet_addr(argv[1]);
    int len = sizeof(sin_t);
    connect(sockfd,(sad_t*)&server,len);

    //设置心跳定时器
    signal(SIGALRM,heartbeat);
    alarm(TIME);

//函数声明
int findall_directory(int sockfd);
int upload_directory(int sockfd);
int download_directory(int sockfd);
void menu_2();
    
    while(1)
    {
        menu();
        printf("请输入你的选择:");
        int choice;
        scanf("%d",&choice);
        getchar();
        if(choice == 0)
        {
            quit(sockfd);
            alarm(TIME);
            break;
        }
        int flag = 0;
        switch(choice)
        {
            case 1:
                //用户登录
                user_login(sockfd);
                break;
            case 2:
                //用户注册
                user_register(sockfd);
                break;
            case 3:
                //用户注销
                user_logout(sockfd);
                break;  
            case 4:
            // 进入二级菜单
               menu_2();
            default:
                puts("输入有误请重新输入");
                flag = 1;
                break;
        }
        if(flag)
            continue;
        /* 4. 接收服务端消息*/
        char bufs[512] = {0};
        recv(sockfd,bufs,sizeof(bufs)-1,0);
        cJSON* servers = cJSON_Parse(bufs);
        if(servers == NULL)
        {
            puts("malloc  node for parse failed");
            return -1;
        }
        alarm(TIME);
            
        cJSON* itemRever = cJSON_GetObjectItem(servers,"rever");
        printf("%s\n",itemRever -> valuestring);
        
        if(strcmp(itemRever -> valuestring,"登录成功!") == 0)
        {
            while(1)
            {
                menu_2();
                printf("请输入你的选择:");
                int choice2;
                scanf("%d",&choice2);
                getchar();
                if(choice2 == 0)
                {
                    alarm(TIME);
                    break;
                }
                int flag2 = 0;
                switch(choice2)
                {
                    case 1:
                        //浏览所有目录信息
                        findall_directory(sockfd);//需要修改
                        break;
                    case 2:
                        //上传所有信息
                        upload_directory(sockfd);

                        break;
                    case 3:
                        //下载所有信息
                        download_directory(sockfd);
                        break;
                    case 4:
                        //返回上一级
                        return  0;
                        break;
                    default:
                        puts("输入有误请重新输入");
                        flag = 1;
                        break;
                }
                alarm(TIME);
                if(flag2)
                    continue;
            }
        }
        cJSON_Delete(servers);
        servers = NULL;
    }

    /* 5. 关闭套接字*/
    close(sockfd);

    return 0;
}

登录界面以及功能实现

c 复制代码
在这里插入代码片

#include "myfun.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include "cJSON.h"
void menu()
{
    printf("\n");
    printf("\033[1;36m");
    printf("================消息系统============\n");
    printf("1. 用户登录\n");
    printf("2. 用户注册\n");
    printf("3. 用户注销\n");
    printf("4. 进入功能\n");
    printf("0. 退出\n");
    printf("===================================\n");
    printf("\033[0m");
    printf("\n");
}

void menu_2()
{
    printf("\n");
    printf("\033[1;36m");
    printf("================消息系统============\n");
    printf("1. 浏览所有目录信息\n");
    printf("2. 上传所有目录信息\n");
    printf("3. 下载所有目录信息\n");
    printf("0. 返回上一级\n");
    printf("===================================\n");
    printf("\033[0m");
    printf("\n");
}

//用户登陆
int user_login(int sockfd)
{
    char user[20] = {0},passwd[8] = {0};
    printf("请输入用户名:");
    fgets(user,20,stdin);
    user[strlen(user)-1] = 0;

    printf("请输入密码:");
    fgets(passwd,8,stdin);
    passwd[strlen(passwd)-1] = 0;

    cJSON* root = cJSON_CreateObject();
    if(root == NULL)
    {
        puts("malloc root node failed");
        return -1;
    }
        
    cJSON_AddStringToObject(root,"request","login");        
    cJSON_AddStringToObject(root,"user",user);       
    cJSON_AddStringToObject(root,"passwd",passwd);

    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd,JSstr1,strlen(JSstr1),0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;
    return 0;
}

//用户注册
int user_register(int sockfd)
{
    char user[20] = {0},passwd[8] = {0};
    printf("请输入用户名:");
    fgets(user,20,stdin);
    user[strlen(user)-1] = 0;
    // getchar();
    

    printf("请输入密码:");
    fgets(passwd,8,stdin);
    passwd[strlen(passwd)-1] = 0;
    sleep(3);
    cJSON* root = cJSON_CreateObject();
    if(root == NULL)
    {
        puts("malloc root node failed");
        return -1;
    }
        
    cJSON_AddStringToObject(root,"request","register");        
    cJSON_AddStringToObject(root,"user",user);       
    cJSON_AddStringToObject(root,"passwd",passwd);

    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd,JSstr1,strlen(JSstr1),0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;
    return 0;
}

//用户注销
int user_logout(int sockfd)
{
    char user[20] = {0},passwd[8] = {0};
    printf("请输入用户名:");
    fgets(user,20,stdin);
    user[strlen(user)-1] = 0;

    printf("请输入密码:");
    fgets(passwd,8,stdin);
    passwd[strlen(passwd)-1] = 0;

    cJSON* root = cJSON_CreateObject();
    if(root == NULL)
    {
        puts("malloc root node failed");
        return -1;
    }
        
    cJSON_AddStringToObject(root,"request","logout");        
    cJSON_AddStringToObject(root,"user",user);       
    cJSON_AddStringToObject(root,"passwd",passwd);

    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd,JSstr1,strlen(JSstr1),0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;
    return 0;
}





// 浏览所有目录以及文件信息
int findall_directory(int sockfd) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        puts("malloc root node failed");
        return -1;
    }
    // 修改请求类型为 findall_directory
    cJSON_AddStringToObject(root, "request", "findall_directory");
    
    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd, JSstr1, strlen(JSstr1), 0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;

    char bufs[1024 * 1024] = {0};
    recv(sockfd, bufs, sizeof(bufs) - 1, 0);
    cJSON* directories = cJSON_Parse(bufs);
    if (directories == NULL) {
        puts("malloc node for parse failed");
        return -1;
    }
    cJSON* itemReverse = cJSON_GetObjectItem(directories, "reverse");
    if (strcmp(itemReverse->valuestring, "null") == 0) {
        cJSON_Delete(directories);
        directories = NULL;
        printf("未有目录信息\n");
        return 0;
    }
    // 解析目录信息
    cJSON* itemType = cJSON_GetObjectItem(directories, "type");
    cJSON* itemTitle = cJSON_GetObjectItem(directories, "title");
    cJSON* itemContent = cJSON_GetObjectItem(directories, "content");
    cJSON* itemData = cJSON_GetObjectItem(directories, "directory");
    // 打印目录信息
    printf("%-18s\t%-70s\t%s\n", itemType->valuestring, itemTitle->valuestring, itemContent->valuestring);
    if (cJSON_IsArray(itemData)) {
        int n = cJSON_GetArraySize(itemData);
        for (int i = 0; i < n; i++) {
            cJSON* subItem = cJSON_GetArrayItem(itemData, i);
            cJSON* itemData_name = cJSON_GetObjectItem(subItem, "name");
            cJSON* itemData_size = cJSON_GetObjectItem(subItem, "size");
            cJSON* itemData_created_date = cJSON_GetObjectItem(subItem, "created_date");
            // 打印目录的详细信息
            printf("%-30s\t%-10d\t%s\n", itemData_name->valuestring, itemData_size->valueint, itemData_created_date->valuestring);
        }
    }
    cJSON_Delete(directories);
    directories = NULL;

    return 0;
}



// 假设的函数,用于收集目录和文件信息到 cJSON 对象
cJSON* collect_directory_and_file_info() {
    cJSON* root = cJSON_CreateObject();
    // 示例:添加一些目录和文件信息
    cJSON* directories = cJSON_AddArrayToObject(root, "directories");
    cJSON* files = cJSON_AddArrayToObject(root, "files");

    // 假设添加一个目录信息
    cJSON* dir1 = cJSON_CreateObject();
    cJSON_AddStringToObject(dir1, "name", "/path/to/directory");
    cJSON_AddNumberToObject(dir1, "size", 1024);
    cJSON_AddStringToObject(dir1, "created_date", "2025-01-12");
    cJSON_AddItemToArray(directories, dir1);

    // 假设添加一个文件信息
    cJSON* file1 = cJSON_CreateObject();
    cJSON_AddStringToObject(file1, "name", "/path/to/file.txt");
    cJSON_AddNumberToObject(file1, "size", 512);
    cJSON_AddStringToObject(file1, "created_date", "2025-01-11");
    cJSON_AddItemToArray(files, file1);

    return root;
}


// 上传所有目录以及文件信息
int upload_directory(int sockfd) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        puts("malloc root node failed");
        return -1;
    }
    // 修改请求类型为 upload_directory
    cJSON_AddStringToObject(root, "request", "upload_directory");

    // 收集目录和文件信息
    cJSON* directory_and_file_info = collect_directory_and_file_info();
    cJSON_AddItemToObject(root, "data", directory_and_file_info);

    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd, JSstr1, strlen(JSstr1), 0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;


    // 接收服务器的响应(可选)
    char bufs[1024 * 1024] = {0};
    recv(sockfd, bufs, sizeof(bufs) - 1, 0);
    cJSON* response = cJSON_Parse(bufs);
    if (response == NULL) {
        puts("malloc node for parse failed");
        return -1;
    }
    cJSON* itemReverse = cJSON_GetObjectItem(response, "reverse");
    if (strcmp(itemReverse->valuestring, "null") == 0) {
        cJSON_Delete(response);
        response = NULL;
        printf("上传失败\n");
        return -1;
    } else {
        printf("上传成功\n");
    }
    cJSON_Delete(response);
    response = NULL;


    return 0;
}




// 下载所有目录及文件信息
int download_directory(int sockfd) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        puts("malloc root node failed");
        return -1;
    }
    // 修改请求类型为 download_directory
    cJSON_AddStringToObject(root, "request", "download_directory");

    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd, JSstr1, strlen(JSstr1), 0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;


    // 接收服务器的响应
    char bufs[1024 * 1024] = {0};
    recv(sockfd, bufs, sizeof(bufs) - 1, 0);
    cJSON* response = cJSON_Parse(bufs);
    if (response == NULL) {
        puts("malloc node for parse failed");
        return -1;
    }
    cJSON* itemReverse = cJSON_GetObjectItem(response, "reverse");
    if (strcmp(itemReverse->valuestring, "null") == 0) {
        cJSON_Delete(response);
        response = NULL;
        printf("没有可下载的目录或文件信息\n");
        return 0;
    } else {
        printf("开始下载目录和文件信息\n");
    }


    // 解析并处理下载的目录和文件信息
    cJSON* directories = cJSON_GetObjectItem(response, "directories");
    cJSON* files = cJSON_GetObjectItem(response, "files");


    if (cJSON_IsArray(directories)) {
        int n = cJSON_GetArraySize(directories);
        for (int i = 0; i < n; i++) {
            cJSON* subItem = cJSON_GetArrayItem(directories, i);
            cJSON* dir_name = cJSON_GetObjectItem(subItem, "name");
            cJSON* dir_size = cJSON_GetObjectItem(subItem, "size");
            cJSON* dir_created_date = cJSON_GetObjectItem(subItem, "created_date");
            // 打印目录信息,可添加下载逻辑
            printf("Directory: %s, Size: %d, Created Date: %s\n", dir_name->valuestring, dir_size->valueint, dir_created_date->valuestring);
        }
    }


    if (cJSON_IsArray(files)) {
        int m = cJSON_GetArraySize(files);
        for (int i = 0; i < m; i++) {
            cJSON* subItem = cJSON_GetArrayItem(files, i);
            cJSON* file_name = cJSON_GetObjectItem(subItem, "name");
            cJSON* file_size = cJSON_GetObjectItem(subItem, "size");
            cJSON* file_created_date = cJSON_GetObjectItem(subItem, "created_date");
            // 打印文件信息,可添加下载逻辑
            printf("File: %s, Size: %d, Created Date: %s\n", file_name->valuestring, file_size->valueint, file_created_date->valuestring);
        }
    }


    cJSON_Delete(response);
    response = NULL;


    return 0;
}





int quit(int sockfd)
{
    cJSON* root = cJSON_CreateObject();
    if(root == NULL)
    {
        puts("malloc root node failed");
        return -1;
    }
        
    cJSON_AddStringToObject(root,"request","quit");        
    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd,JSstr1,strlen(JSstr1),0);
    cJSON_Delete(root);
    free(JSstr1);
    root = NULL;
    return 0;
}

需要引用cJSON文件 json文件:

服务器端自己构建函数mufun.c

c 复制代码
#include "myfun.h"
#include<dirent.h>
#include<sys/stat.h>

typedef unsigned long long ull;

//数据库连接
static MYSQL* mysql_connect()
{
    //数据库初始化
    MYSQL* mysql = mysql_init(NULL);
    if(mysql == NULL)
    {
        fprintf(stderr,"mysql_init初始化失败\n");
        return NULL;
    }
    mysql_set_character_set(mysql,"utf8");
    //数据库连接
    if(NULL == mysql_real_connect(mysql,"localhost","root","123456","xiaohua",0,NULL,0))
    {
        fprintf(stderr,"conn:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return NULL; 
    }
    return mysql;
}

//登录
int login(const char* user,const char* passwd)
{
    MYSQL* mysql = mysql_connect();
    char sql[128] = {0};
    sprintf(sql,"select * from users");
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        fprintf(stderr,"exec:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return 0; 
    }
    //获得字符集
    MYSQL_RES *result = mysql_store_result(mysql);
    if(result == NULL)
    {
        fprintf(stderr,"store res:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return 0; 
    }
    ull rnum = mysql_num_rows(result);//记录数量

    for(int i = 0; i  < rnum; i++)
    {
        MYSQL_ROW row = mysql_fetch_row(result);
        if(strcmp(row[0],user) == 0 && strcmp(row[1],passwd) == 0)
        {
            mysql_free_result(result);
            char sql2[128] = {0};
            sprintf(sql2,"update users set state = 1 where username = '%s'",user);
            mysql_real_query(mysql,sql2,strlen(sql2));
            mysql_close(mysql);
            return 1;
        }
    }
    mysql_free_result(result);
    mysql_close(mysql);
    return 0;
}

//注册
int regist(const char* user,const char* passwd)
{
    
    MYSQL* mysql = mysql_connect();
    char sql1[128] = {0};
    sprintf(sql1,"create table if not exists users(username varchar(20) primary key,passwd varchar(8) not null,state int default 0)default charset=utf8");
    if(mysql_real_query(mysql,sql1,strlen(sql1)))
    {
        fprintf(stderr,"exec:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return 0; 
    }
    char sql2[128] = {0};
    sprintf(sql2,"insert into users(username,passwd) values('%s','%s')",user,passwd);
    if(mysql_real_query(mysql,sql2,strlen(sql2)))
    {
        fprintf(stderr,"exec:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return 0; 
    }
    mysql_close(mysql);
    return 1;
}

//注销
int logout(const char* user,const char* passwd)
{
    MYSQL* mysql = mysql_connect();
    char sql[128] = {0};
    sprintf(sql,"select * from users");
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        fprintf(stderr,"exec:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return 0; 
    }
    //获得字符集
    MYSQL_RES *result = mysql_store_result(mysql);
    if(result == NULL)
    {
        mysql_close(mysql);
        return 0; 
    }
    ull rnum = mysql_num_rows(result);//记录数量

    for(int i = 0; i  < rnum; i++)
    {
        MYSQL_ROW row = mysql_fetch_row(result);
        if(strcmp(row[0],user) == 0 && strcmp(row[1],passwd) == 0)
        {
            char sql2[128] = {0};
            sprintf(sql2,"delete from users where username = '%s'",user);
            if(mysql_real_query(mysql,sql2,strlen(sql2)))
            {
                fprintf(stderr,"exec:%s\n",mysql_error(mysql));
                mysql_close(mysql);
                return 0; 
            }
            mysql_free_result(result);
            mysql_close(mysql);
            return 1;
        }
    }
    mysql_free_result(result);
    mysql_close(mysql);
    return 0;   
}






// 浏览所有目录文件信息
int findall_directory(int sockfd) {
    MYSQL* mysql = mysql_connect();
    if (mysql == NULL) {
        fprintf(stderr, "Failed to connect to MySQL database.\n");
        return -1;
    }


    char sql1[128] = {0};
    cJSON* root = cJSON_CreateObject();
    // 假设表名为 directories_files,包含目录和文件信息
    sprintf(sql1, "select * from xiaohua");


    if (mysql_real_query(mysql, sql1, strlen(sql1))) {
        fprintf(stderr, "Failed to execute SQL query: %s\n", mysql_error(mysql));
        mysql_close(mysql);
        cJSON_AddStringToObject(root, "reverse", "null");
        char* JSstr1 = cJSON_PrintUnformatted(root);
        send(sockfd, JSstr1, strlen(JSstr1), 0);
        return 0;
    }


    MYSQL_RES *result = mysql_store_result(mysql);
    if (result == NULL) {
        fprintf(stderr, "Failed to store query result: %s\n", mysql_error(mysql));
        mysql_close(mysql);
        cJSON_AddStringToObject(root, "reverse", "null");
        char* JSstr1 = cJSON_PrintUnformatted(root);
        send(sockfd, JSstr1, strlen(JSstr1), 0);
        return -1;
    }


    uint32_t fnum = mysql_num_fields(result);
    my_ulonglong rnum = mysql_num_rows(result);
    // 获得列名
    MYSQL_FIELD *fields = mysql_fetch_fields(result);
    cJSON_AddStringToObject(root, "reverse", "not null");
    // 假设表的列名为 dir_name, file_name, size, created_date
    cJSON_AddStringToObject(root, "dir_name", fields[0].name);
    cJSON_AddStringToObject(root, "file_name", fields[1].name);
    cJSON_AddStringToObject(root, "size", fields[2].name);
    cJSON_AddStringToObject(root, "created_date", fields[3].name);


    cJSON* array = cJSON_CreateArray();


    for (int i = 0; i < rnum; i++) {
        cJSON* obj = cJSON_CreateObject();
        MYSQL_ROW row = mysql_fetch_row(result);
        for (int j = 0; j < fnum; j++) {
            cJSON_AddStringToObject(obj, fields[j].name, row[j]);
        }
        cJSON_AddItemToArray(array, obj);
    }


    cJSON_AddItemToObject(root, "data", array);


    mysql_free_result(result);
    mysql_close(mysql);


    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd, JSstr1, strlen(JSstr1), 0);


    cJSON_Delete(root);


    return 0;
}






// 上传所有目录文件
int upload_directory(int sockfd) {
    cJSON* root = cJSON_CreateObject();
    cJSON* array = cJSON_CreateArray();


    // 打开当前目录
    DIR* dir = opendir(".");
    if (dir == NULL) {
        perror("opendir");
        cJSON_AddStringToObject(root, "reverse", "null");
        char* JSstr1 = cJSON_PrintUnformatted(root);
        send(sockfd, JSstr1, strlen(JSstr1), 0);
        cJSON_Delete(root);
        return -1;
    }


    struct dirent* entry;
    while ((entry = readdir(dir))!= NULL) {
        if (entry->d_name[0] == '.') continue; // 跳过隐藏文件和目录


        struct stat st;
        if (stat(entry->d_name, &st) == -1) {
            perror("stat");
            continue;
        }


        cJSON* obj = cJSON_CreateObject();
        cJSON_AddStringToObject(obj, "name", entry->d_name);
        cJSON_AddNumberToObject(obj, "size", (int)st.st_size);
        cJSON_AddStringToObject(obj, "type", S_ISDIR(st.st_mode)? "directory" : "file");


        // 获取文件的创建时间
        char time_str[20];
        strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", localtime(&st.st_ctime));
        cJSON_AddStringToObject(obj, "created_date", time_str);


        cJSON_AddItemToArray(array, obj);
    }


    closedir(dir);


    cJSON_AddItemToObject(root, "data", array);
    cJSON_AddStringToObject(root, "request", "upload_directory");


    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd, JSstr1, strlen(JSstr1), 0);


    cJSON_Delete(root);
    free(JSstr1);


    return 0;
}






// 下载所有目录文件信息
int download_directory(int sockfd) {
    cJSON* root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "request", "download_directory");


    // 将请求信息发送到服务器
    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd, JSstr1, strlen(JSstr1), 0);
    cJSON_Delete(root);
    free(JSstr1);


    // 接收服务器的响应
    char buffer[4096];
    int bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
    if (bytes_received <= 0) {
        perror("recv");
        return -1;
    }
    buffer[bytes_received] = '\0';


    // 解析服务器的响应
    cJSON* response = cJSON_Parse(buffer);
    if (response == NULL) {
        fprintf(stderr, "Failed to parse JSON response\n");
        return -1;
    }


    // 检查服务器是否返回错误信息
    cJSON* reverse = cJSON_GetObjectItem(response, "reverse");
    if (reverse!= NULL && strcmp(reverse->valuestring, "null") == 0) {
        fprintf(stderr, "Server returned an error\n");
        cJSON_Delete(response);
        return -1;
    }


    // 假设服务器返回的数据在 "data" 键下
    cJSON* data = cJSON_GetObjectItem(response, "data");
    if (data == NULL ||!cJSON_IsArray(data)) {
        fprintf(stderr, "Invalid data format from server\n");
        cJSON_Delete(response);
        return -1;
    }


    // 遍历服务器返回的目录文件信息
    int array_size = cJSON_GetArraySize(data);
    for (int i = 0; i < array_size; i++) {
        cJSON* item = cJSON_GetArrayItem(data, i);
        if (item == NULL) continue;


        cJSON* name = cJSON_GetObjectItem(item, "name");
        cJSON* size = cJSON_GetObjectItem(item, "size");
        cJSON* type = cJSON_GetObjectItem(item, "type");
        cJSON* created_date = cJSON_GetObjectItem(item, "created_date");


        if (name == NULL || size == NULL || type == NULL || created_date == NULL) {
            fprintf(stderr, "Invalid item format from server\n");
            continue;
        }


        // 这里可以添加逻辑将文件或目录信息保存到本地
        // 例如,打印文件或目录信息
        printf("Name: %s, Size: %d, Type: %s, Created Date: %s\n", name->valuestring, size->valueint, type->valuestring, created_date->valuestring);
    }


    cJSON_Delete(response);


    return 0;
}






int check(int sockfd,const char* user)
{
    MYSQL* mysql = mysql_connect();
    char sql1[128] = {0};
    cJSON* root = cJSON_CreateObject();
    sprintf(sql1,"select * from unread where username = '%s'",user);
    if(mysql_real_query(mysql,sql1,strlen(sql1)))
    {
        mysql_close(mysql);
        cJSON_AddStringToObject(root,"reverse","null");
        char* JSstr1 = cJSON_PrintUnformatted(root);
        send(sockfd,JSstr1,strlen(JSstr1),0);
        return 0; 
    }
    MYSQL_RES *result = mysql_store_result(mysql);
    if(result == NULL)
    {
        mysql_close(mysql);
        cJSON_AddStringToObject(root,"reverse","null");
        char* JSstr1 = cJSON_PrintUnformatted(root);
        send(sockfd,JSstr1,strlen(JSstr1),0);
        return -1; 
    }
    uint32_t      fnum = mysql_num_fields(result);
    my_ulonglong  rnum = mysql_num_rows(result);
    //获得列名
    MYSQL_FIELD *fields = mysql_fetch_fields(result);
    cJSON_AddStringToObject(root,"reverse","not null");
    cJSON_AddStringToObject(root,"type",fields[1].name);
    cJSON_AddStringToObject(root,"title",fields[2].name);
    cJSON_AddStringToObject(root,"content",fields[3].name);

    cJSON* array = cJSON_CreateArray();

    for(int i = 0; i  < rnum; i++)
    {
        MYSQL_ROW  row = mysql_fetch_row(result);
        cJSON* obj = cJSON_CreateObject();
        for(int j = 1; j < fnum; j++)
        {
            cJSON_AddStringToObject(obj,fields[j].name,row[j]);
        }
            
        cJSON_AddItemToArray(array,obj);
    }
    cJSON_AddItemToObject(root,"data",array);
    mysql_free_result(result);
    char sql2[128] = {0};
    sprintf(sql2,"delete from unread where username = '%s'",user);
    mysql_real_query(mysql,sql2,strlen(sql2));

    mysql_close(mysql);

    char* JSstr1 = cJSON_PrintUnformatted(root);
    send(sockfd,JSstr1,strlen(JSstr1),0);
    
    return 0;
}

//退出
int quit(const char* user)
{
    MYSQL* mysql = mysql_connect();
    char sql[128] = {0};
    sprintf(sql,"update users set state = 0 where username = '%s'",user);
    if(mysql_real_query(mysql,sql,strlen(sql)))
    {
        fprintf(stderr,"exec:%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return -1; 
    }
    mysql_close(mysql);
    return 0;
}

服务器端fock.c

c 复制代码
在这里插入代码片

#include "mysock.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include "cJSON.h"
#include <dirent.h>
#include <sys/stat.h>
#include <arpa/inet.h>


// 假设以下函数在其他地方实现,在此声明它们
int findall_directory(int sockc);
int download_directory(int sockc);
int upload_directory(int sokc);
int login(const char *user, const char *passwd);
int regist(const char *user, const char *passwd);
int logout(const char *user, const char *passwd);
int  quit(const char *user);


/*监听函数,返回监听套接字*/
int mysock_init(const char *Ip, const char *Port)
{
    /* 1. 创建套接字*/
    int sockl = socket(AF_INET, SOCK_STREAM, 0);
    if (sockl == -1)
        return -1;


    /* 2. 绑定自己地址信息*/
    struct sockaddr_in server = {0};
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(Port));
    inet_pton(AF_INET, Ip, &server.sin_addr); //将字符串变成网络字节序
    socklen_t len = sizeof(server);
    if (-1 == bind(sockl, (struct sockaddr *)&server, len))
    {
        close(sockl);
        return -1;
    }


    /* 3. 监听客户端连接*/
    if (-1 == listen(sockl, 5))
    {
        close(sockl);
        return -1;
    }


    //返回监听套接字
    return sockl;
}


char user_name[20] = {0};


/*连接函数,接收客户端连接*/
int mysock_accept(int sockl)
{
    struct sockaddr_in peer = {0}; //对方
    socklen_t len = sizeof(peer);
    int sockc = accept(sockl, (struct sockaddr *)&peer, &len);
    if (sockc == -1)
        return -1;
    char IP[INET_ADDRSTRLEN + 1];
    inet_ntop(AF_INET, &peer.sin_addr, IP, INET_ADDRSTRLEN);
    printf("[%s:%d]已连接\n", IP, ntohs(peer.sin_port));


    //生成连接套接字
    return sockc;
}


/* 接收客户端信息的函数*/
void *from_client(void *argp)
{
    int sockc = *(int *)argp;
    struct sockaddr_in peer = {0};
    socklen_t len = sizeof(peer);
    getpeername(sockc, (struct sockaddr *)&peer, &len);


    // 获取客户端地址信息
    while (1)
    {
        char str[512] = {0};
        int n = recv(sockc, str, sizeof(str), 0);
        if (n == 0)
        {
            printf("客户端[%s:%d]已断开连接\n", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));
            quit(user_name);
            break;
        }
        /* 处理客户端请求*/
        to_client(str, sockc);
    }
    return NULL;
}


void to_client(const char *jsStr, int sockc)
{
    /* 给客户端发消息*/
    cJSON *root = cJSON_Parse(jsStr);
    if (root == NULL)
        return;


    cJSON *itemRequest = cJSON_GetObjectItem(root, "request");
    cJSON *itemUser = cJSON_GetObjectItem(root, "user");
    cJSON *itemPasswd = cJSON_GetObjectItem(root, "passwd");


   
    //登录
    if (strcmp(itemRequest->valuestring, "login") == 0)
    {
        puts("用户登录");
        char *res[] = {"登录失败!", "登录成功!"};
        int i = login(itemUser->valuestring, itemPasswd->valuestring);
        cJSON *rever = cJSON_CreateObject();
        if (rever == NULL)
            return;
        if (i == 1)
        {
            memset(user_name, 0, 20);
            strcpy(user_name, itemUser->valuestring);
        }
        cJSON_AddStringToObject(rever, "rever", res[i]);
        char *JSstr1 = cJSON_PrintUnformatted(rever);
        send(sockc, JSstr1, strlen(JSstr1), 0);
        cJSON_Delete(rever);
    }
    //注册
    else if (strcmp(itemRequest->valuestring, "register") == 0)
    {
        puts("用户注册");
        char *res[] = {"注册失败!", "注册成功,请登录..."};
        int i = regist(itemUser->valuestring, itemPasswd->valuestring);
        cJSON *rever = cJSON_CreateObject();
        if (rever == NULL)
            return;
        cJSON_AddStringToObject(rever, "rever", res[i]);
        char *JSstr1 = cJSON_PrintUnformatted(rever);
        send(sockc, JSstr1, strlen(JSstr1), 0);
        cJSON_Delete(rever);
    }
    //注销
    else if (strcmp(itemRequest->valuestring, "logout") == 0)
    {
        puts("用户注销");
        char *res[] = {"注销失败!", "注销成功!"};
        int i = logout(itemUser->valuestring, itemPasswd->valuestring);
        cJSON *rever = cJSON_CreateObject();
        if (rever == NULL)
            return;
        cJSON_AddStringToObject(rever, "rever", res[i]);
        char *JSstr1 = cJSON_PrintUnformatted(rever);
        send(sockc, JSstr1, strlen(JSstr1), 0);
        cJSON_Delete(rever);
    }


    // 浏览所有目录文件信息
    else if (strcmp(itemRequest->valuestring, "findall_directory") == 0)
    {
        puts("浏览所有目录文件信息");
        findall_directory(sockc);
    }


    // 上传目录文件信息
    else if (strcmp(itemRequest->valuestring, "upload_directory") == 0)
    {
        puts("上传目录文件信息");
        int upload_directory(int sockc) {
            cJSON *root = cJSON_CreateObject();
            cJSON *array = cJSON_CreateArray();


            DIR *dir = opendir(".");
            if (dir == NULL) {
                perror("opendir");
                cJSON_AddStringToObject(root, "reverse", "null");
                char *JSstr = cJSON_PrintUnformatted(root);
                send(sockc, JSstr, strlen(JSstr), 0);
                cJSON_Delete(root);
                free(JSstr);
                return -1;
            }


            struct dirent *entry;
            while ((entry = readdir(dir))!= NULL) {
                if (entry->d_name[0] == '.') continue;


                struct stat st;
                if (stat(entry->d_name, &st) == -1) {
                    perror("stat");
                    continue;
                }


                cJSON *obj = cJSON_CreateObject();
                cJSON_AddStringToObject(obj, "name", entry->d_name);
                cJSON_AddNumberToObject(obj, "size", (int)st.st_size);
                cJSON_AddStringToObject(obj, "type", S_ISDIR(st.st_mode)? "directory" : "file");


                cJSON_AddItemToArray(array, obj);
            }


            closedir(dir);


            cJSON_AddItemToObject(root, "data", array);
            cJSON_AddStringToObject(root, "request", "upload_directory");


            char *JSstr = cJSON_PrintUnformatted(root);
            send(sockc, JSstr, strlen(JSstr), 0);


            cJSON_Delete(root);
            free(JSstr);


            return 0;
        }
        upload_directory(sockc);
    }


    // 下载所有目录信息
    else if (strcmp(itemRequest->valuestring, "download_directory") == 0)
    {
        puts("下载所有目录信息");
        // 假设 download_directory 函数的参数为 sockc
        download_directory(sockc);
    }


    //检测是否退出
    else if (strcmp(itemRequest->valuestring, "quit") == 0)
    {
        quit(user_name);
    }
    //心跳检测机制
    else if (strcmp(itemRequest->valuestring, "heartbeat") == 0)
    {
        struct sockaddr_in peer = {0}; //对方
        socklen_t len = sizeof(peer);
        getpeername(sockc, (struct sockaddr *)&peer, &len);
        char IP[INET_ADDRSTRLEN + 1];
        inet_ntop(AF_INET, &peer.sin_addr, IP, INET_ADDRSTRLEN);
        printf("[%s:%d]还在连接中\n", IP, ntohs(peer.sin_port));
    }


    cJSON_Delete(root);
}

服务器端 server.c

c 复制代码
#include "myfun.h"
#include "mysock.h"
#include "pthreadpool.h"

int main(int argc,char **argv)
{
    if(argc < 3)
    {
        fprintf(stderr,"Usage <%s SERIP SERPOST>\n",argv[0]);
        return -1;
    }
    //调用函数
    threadpool_t pool;
    threadpool_init(&pool,8,10);
    /* 1. 调用监听函数*/
    int sockl = mysock_init(argv[1],argv[2]);
    if(sockl == -1)
    {
        perror("mysock_init");
        return -1;
    }
    
    while(1)
    {
        /* 2.调用连接函数,接收客户端连接*/
        int sockc = mysock_accept(sockl);
        if(sockc == -1)
            continue;
            
        threadpool_addtask(&pool,from_client,(void*)(uint64_t)sockc);
    }

    return 0;
}

服务器pthreadPool.c

c 复制代码
#include "pthreadpool.h"
#include <stdlib.h>

void* thread_fun(void *argp)
{
    threadpool_t* pool = (threadpool_t*)argp;
    task_t    *p = NULL;
    while(1)
    {
        //互斥锁
        pthread_mutex_lock(&pool->mutex);
        //判断队列情况
        //任务队列为空等待
        while(pool -> queue_num == 0)
            pthread_cond_wait(&pool->queue_empty,&pool->mutex);
        //任务队列不为空,被线程池中线程竞争
        p = pool -> head;
        pool -> queue_num--;
        //表示任务队列只有一个节点
        if(pool -> queue_num == 0)
            pool -> head = pool -> tail = NULL;
        else
            pool -> head = p -> next;
        //判断任务队列是否为满通知其他线程
        if(pool->queue_num == pool -> queue_max_size -1)
            pthread_cond_signal(&pool->queue_full);

        pthread_mutex_unlock(&pool->mutex);
        //调用函数
        (*(p -> taskfun))(p -> argp);
        //调用完毕回收资源
        free(p);
        p = NULL;
    }
}
相关推荐
lilili啊啊啊1 小时前
IOS HTTPS代理抓包工具使用教程
网络协议·http·https
来自于狂人1 小时前
隧道网络:为数据传输开辟安全通道
网络·计算机网络·安全
小庞在加油2 小时前
【C++开源库】Boost.Asio网络库使用介绍
网络·c++·开源·boost网络库
木人舟2 小时前
在VMware配置Ubuntu20.04静态ip的方法
网络·网络协议·tcp/ip
MC何失眠2 小时前
vulnhub靶场【DC系列】之7
网络·学习·安全·web安全·网络安全
一张假钞2 小时前
解决HTTP POST请求Nginx静态内容405错误
网络·网络协议·http
IPdodo全球网络服务2 小时前
ChatGPT 网络配置问题解决方案
网络·chatgpt
神一样的老师3 小时前
【行空板K10】上传温湿度信息到EasyIoT平台
网络·嵌入式硬件·物联网·青少年编程
迃幵chen3 小时前
高可用虚拟IP-keepalived
linux·服务器·tcp/ip
dog2503 小时前
互联网架构变迁:从 TCP/IP “呼叫” 到 NDN “内容分发” 的逐浪之旅
网络·tcp/ip·架构