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

在这里插入图片描述
客户端代码

需要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[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;
}

登录界面以及功能实现

在这里插入代码片#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_directorycJSON_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_directorycJSON_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_directorycJSON_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

#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_datecJSON_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

在这里插入代码片#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 函数的参数为 sockcdownload_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

#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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/66936.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Type-C双屏显示器方案

在数字化时代&#xff0c;高效的信息处理和视觉体验已成为我们日常生活和工作的关键需求。随着科技的进步&#xff0c;一款结合了便携性和高效视觉输出的设备——双屏便携屏&#xff0c;逐渐崭露头角&#xff0c;成为追求高效工作和娱乐体验人群的新宠。本文将深入探讨双屏便携…

计算机视觉算法实战——车道线检测

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​ ​​​​​​​​​​​​ ​​​​​ 车道线检测是计算机视觉领域的一个重要研究方向&#xff0c;尤其在自动驾驶和高级驾驶辅助…

【微服务】面试 3、 服务监控 SkyWalking

微服务监控的原因 问题定位&#xff1a;在微服务架构中&#xff0c;客户端&#xff08;如 PC 端、APP 端、小程序等&#xff09;请求后台服务需经过网关再路由到各个微服务&#xff0c;服务间可能存在多链路调用。当某一微服务挂掉时&#xff0c;在复杂的调用链路中难以迅速确定…

【MySQL数据库】基础总结

目录 前言 一、概述 二、 SQL 1. SQL通用语法 2. SQL分类 3. DDL 3.1 数据库操作 3.2 表操作 4. DML 5. DQL 5.1 基础查询 5.2 条件查询 5.3 聚合函数 5.4 分组查询 5.5 排序查询 5.6 分页查询 6. DCL 6.1 管理用户 6.2 权限控制 三、数据类型 1. 数值类…

aws(学习笔记第二十三课) step functions进行开发(lambda函数调用)

aws(学习笔记第二十三课) 开发step functions状态机的应用程序 学习内容&#xff1a; step functions状态机的概念开发简单的step functions状态机 1. step functions状态机概念 官方说明文档和实例程序 AWS的官方给出了学习的链接和实例程序。使用SAM创建step functions 借…

【Docker】入门教程

目录 一、Docker的安装 二、Docker的命令 Docker命令实验 1.下载镜像 2.启动容器 3.修改页面 4.保存镜像 5.分享社区 三、Docker存储 1.目录挂载 2.卷映射 四、Docker网络 1.容器间相互访问 2.Redis主从同步集群 3.启动MySQL 五、Docker Compose 1.命令式安装 …

算法练习7——拦截导弹的系统数量求解

题目描述 某国为了防御敌国的导弹袭击&#xff0c;发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷&#xff1a;虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都不能高于前一发的高度。 假设某天雷达捕捉到敌国的导弹来袭。由于该系统还在试用…

如何使用高性能内存数据库Redis

一、详细介绍 1.1、Redis概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。Redis支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;、哈希&am…

【Linux系列】`find / -name cacert.pem` 文件搜索

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

UE材质Fab Megascans

2025年Bridge里已经不能直接导入资产了&#xff0c;显示GET IT ON FAB 只能在Fab中导入资产&#xff0c; 纹理打包技术从RMA改成了ORM O&#xff1a;AO 环境光遮蔽 R&#xff1a;Roughness 粗糙度 M&#xff1a;Metallic 金属度 在Fab中找到材质&#xff0c;点击Add to P…

【NP-hard问题】NP与NP-hard问题通俗解释

最近在研究NP-hard问题&#xff0c;讲一下自己的对于NP与NP-hard问题的通俗解释 一、NP-Hard 问题是什么意思&#xff1f; 什么是 NP&#xff1f; NP 问题可以理解为「检查答案很容易&#xff0c;但找到答案很难」。 举个例子&#xff1a; 假设你在一个迷宫里&#xff0c;…

ollama教程(window系统)

前言 在《本地大模型工具哪家强&#xff1f;对比Ollama、LocalLLM、LM Studio》一文中对比了三个常用的大模型聚合工具优缺点&#xff0c;本文将详细介绍在window操作系统下ollama的安装和使用。要在 Windows 上安装并使用 Ollama&#xff0c;需要依赖 NVIDIA 显卡&#xff0c…

[论文阅读] (35)TIFS24 MEGR-APT:基于攻击表示学习的高效内存APT猎杀系统

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…

半导体数据分析: 玩转WM-811K Wafermap 数据集(三) AI 机器学习

前面我们已经通过两篇文章&#xff0c;一起熟悉了WM-811K Wafermap 数据集&#xff0c;并对其中的一些数据进行了调用&#xff0c;生成了一些统计信息和图片。今天我们接着继续往前走。 半导体数据分析&#xff1a; 玩转WM-811K Wafermap 数据集&#xff08;二&#xff09; AI…

BGP 泄露

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 目录 1. BGP 是什么&#xff1f; 2. 什么是 BGP 泄露&#xff1f; 3. 今天发生了什么&#xff1f; 4. 正常和被劫持状态下的路由示意图 5. 受影响区域 6. 责任在谁&#xff1f; 7. 有办法避免这…

wireshark排除私接小路由

1.wireshark打开&#xff0c;发现了可疑地址&#xff0c;合法的地址段DHCP是192.168.100.0段的&#xff0c;打开后查看发现可疑地址段&#xff0c;分别是&#xff0c;192.168.0.1 192.168.1.174 192.168.1.1。查找到它对应的MAC地址。 ip.src192.168.1.1 2.通过show fdb p…

使用 CompletableFuture 实现异步编程

在现代 Java 开发中&#xff0c;异步编程是一项重要技能。而 CompletableFuture 是从 Java 8 开始提供的一个功能强大的工具&#xff0c;用于简化异步任务的编写和组合。本文将详细介绍 CompletableFuture 的基本使用和一些常见的应用场景。 1. 为什么选择 CompletableFuture&…

AWS云计算概览(自用留存,整理中)

目录 一、云概念概览 &#xff08;1&#xff09;云计算简介 &#xff08;2&#xff09;云计算6大优势 &#xff08;3&#xff09;web服务 &#xff08;4&#xff09;AWS云采用框架&#xff08;AWS CAF&#xff09; 二、云经济学 & 账单 &#xff08;1&#xff09;定…

【江协STM32】10-4/5 I2C通信外设、硬件I2C读写MPU6050

1. I2C外设简介 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能&#xff0c;减轻CPU的负担支持多主机模型支持7位/10位地址模式支持不同的通讯速度&#xff0c;标准速度(高达100 kHz)&#xff0c;快速…

Web开发中页面出现乱码的解决(Java Web学习笔记:需在编译时用 -encoding utf-8)

目录 1 引言2 乱码表现、原因分析及解决2.1 乱码表现2.2 原因分析2.3 解决 3 总结 1 引言 Web开发的页面出现了乱码&#xff0c;一直不愿写出来&#xff0c;因为网上的解决方案太多了。但本文的所说的页面乱码问题&#xff0c;则是与网上的大多数解决方案不一样&#xff0c;使…