钜形不锈钢水箱 发表于 2025-1-15 20:08:18

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

https://i-blog.csdnimg.cn/direct/1b04b79525bb4de2be6ff58a5d3ea52e.png
客户端代码
须要cJSON.c文件和cJSON.h文件
在这里插入代码片

#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);
      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));
    server.sin_addr.s_addr = inet_addr(argv);
    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 = {0};
      recv(sockfd,bufs,sizeof(bufs)-1,0);
      cJSON* servers = cJSON_Parse(bufs);
      if(servers == NULL)
      {
            puts("mallocnode 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:
                        //返回上一级
                        return0;
                        break;
                  default:
                        puts("输入有误请重新输入");
                        flag = 1;
                        break;
                }
                alarm(TIME);
                if(flag2)
                  continue;
            }
      }
      cJSON_Delete(servers);
      servers = NULL;
    }

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

    return 0;
}

登录界面以及功能实现
在这里插入代码片

#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 = {0},passwd = {0};
    printf("请输入用户名:");
    fgets(user,20,stdin);
    user = 0;

    printf("请输入密码:");
    fgets(passwd,8,stdin);
    passwd = 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 = {0},passwd = {0};
    printf("请输入用户名:");
    fgets(user,20,stdin);
    user = 0;
    // getchar();
   

    printf("请输入密码:");
    fgets(passwd,8,stdin);
    passwd = 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 = {0},passwd = {0};
    printf("请输入用户名:");
    fgets(user,20,stdin);
    user = 0;

    printf("请输入密码:");
    fgets(passwd,8,stdin);
    passwd = 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 = {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 = {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 = {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


#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 = {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,user) == 0 && strcmp(row,passwd) == 0)
      {
            mysql_free_result(result);
            char sql2 = {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 = {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 = {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 = {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,user) == 0 && strcmp(row,passwd) == 0)
      {
            char sql2 = {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 = {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.name);
    cJSON_AddStringToObject(root, "file_name", fields.name);
    cJSON_AddStringToObject(root, "size", fields.name);
    cJSON_AddStringToObject(root, "created_date", fields.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.name, row);
      }
      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 == '.') 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;
      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;
    int bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
    if (bytes_received <= 0) {
      perror("recv");
      return -1;
    }
    buffer = '\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 = {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_ulonglongrnum = mysql_num_rows(result);
    //获得列名
    MYSQL_FIELD *fields = mysql_fetch_fields(result);
    cJSON_AddStringToObject(root,"reverse","not null");
    cJSON_AddStringToObject(root,"type",fields.name);
    cJSON_AddStringToObject(root,"title",fields.name);
    cJSON_AddStringToObject(root,"content",fields.name);

    cJSON* array = cJSON_CreateArray();

    for(int i = 0; i< rnum; i++)
    {
      MYSQL_ROWrow = mysql_fetch_row(result);
      cJSON* obj = cJSON_CreateObject();
      for(int j = 1; j < fnum; j++)
      {
            cJSON_AddStringToObject(obj,fields.name,row);
      }
            
      cJSON_AddItemToArray(array,obj);
    }
    cJSON_AddItemToObject(root,"data",array);
    mysql_free_result(result);
    char sql2 = {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 = {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
在这里插入代码片

#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);
intquit(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 = {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_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 = {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);
      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);
      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);
      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 == '.') 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_ntop(AF_INET, &peer.sin_addr, IP, INET_ADDRSTRLEN);
      printf("[%s:%d]还在连接中\n", IP, ntohs(peer.sin_port));
    }


    cJSON_Delete(root);
}
服务器端 server.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);
      return -1;
    }
    //调用函数
    threadpool_t pool;
    threadpool_init(&pool,8,10);
    /* 1. 调用监听函数*/
    int sockl = mysock_init(argv,argv);
    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

#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;
    }
}


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 一.项目课题 <基于TCP的文件传输协议实现>