客户端代码
需要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_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
#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
在这里插入代码片
#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
#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;
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;
}
}