C语言多人聊天室 ---s(服务端)
head.h
#ifndef __HEAD_H
#define __HEAD_H
// 常用头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 网络编程涉及的头文件
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
// 本机字节序和网络字节序转换相关函数的头文件
#include <arpa/inet.h>
// 关闭套接字用close函数需要的头文件
#include <unistd.h>
//线程相关的函数头, mutex相关的函数
#include <pthread.h>
// 类型重命名:地址结构体的规范
typedef struct sockaddr SockAddr;
// 地址结构体的规范的实现结构体
typedef struct sockaddr_in SockAddrIn;
// if_nametoindex
#include <net/if.h>
#include <sys/select.h>
#include <sys/time.h>
// JSON字符串的封装
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 文件操作需要的头文件
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "cJSON-master/cJSON.h"
#include <fcntl.h>
#include <mysql/mysql.h>
#include "TCPserver.h"
#include "sql.h"
#include "json.h"
// 定义外部变量
//int sockfdNUM[10] = {0};
#endif
json.h
#ifndef __JSON_H
#define __JSON_H
#include "head.h"
#include "cJSON-master/cJSON.h"
typedef struct // 设置字节不对其齐
{
char option[2];
char name[20];
char pass[20];
} __attribute__((packed)) data;
// 解析json为data类型
data *login_user(char *buf);
// 把数据打包成json格式
char *packingJsontoString(int s_sockfd, char *option, char *name, char *password);
#endif
json.c
#include "json.h"
// typedef struct // 设置字节不对其齐
// {
// char option;
// char name[20];
// char pass[20];
// } __attribute__((packed)) data;
// 把json格式的字符串解析成data结构体
data *login_user(char *buf)
{
data *tmp = (data *)malloc(sizeof(data));
// 1.调用cJSON库中的cJSON_Parse函数解析json格式的字符串
cJSON *root = cJSON_Parse(buf);
if (root == NULL)
{
puts("login_user:解析失败");
// 若解析失败,跳转到结束部分进行资源清理
/// goto end;
}
// 从根对象中获取名为 "name" 的JSON项
cJSON *name = cJSON_GetObjectItem(root, "name");
// 检查 "name" 项是否存在,是否为字符串类型,且字符串值不为空
if (name != NULL && cJSON_IsString(name) && name->valuestring != NULL)
{
// 打印 "name" 项的值
printf("name: %s\n", name->valuestring);
strcpy(tmp->name, name->valuestring);
}
// 从根对象中获取名为 "password" 的JSON项
cJSON *password = cJSON_GetObjectItem(root, "password");
// 检查 "password" 项是否存在,是否为字符串类型,且字符串值不为空
if (password != NULL && cJSON_IsString(password) && password->valuestring != NULL)
{
// 打印 "password" 项的值
printf("password: %s\n", password->valuestring);
strcpy(tmp->pass, password->valuestring);
}
// 从根对象中获取名为 "option" 的JSON项
cJSON *option = cJSON_GetObjectItem(root, "option");
// 检查 "password" 项是否存在,是否为字符串类型,且字符串值不为空
if (option != NULL && cJSON_IsString(option) && option->valuestring != NULL)
{
// 打印 "option" 项的值
printf("option: %s\n", option->valuestring);
strcpy(tmp->option, option->valuestring);
}
// 释放cJSON对象占用的内存
cJSON_Delete(root);
return tmp;
}
// 把数据打包成json格式
char *packingJsontoString(int s_sockfd, char *option, char *name, char *password)
{
// 1.创建json对象
cJSON *root = cJSON_CreateObject(); // 创建根JSON对象
if (root == NULL)
{
puts("packingJsontoString:创建json对象失败");
return NULL; // 若创建失败,返回NULL
}
cJSON *nameItem = cJSON_CreateString(name);
cJSON_AddStringToObject(root, "name", name);
cJSON *passwordInfo = cJSON_CreateString(password);
cJSON_AddStringToObject(root, "password", password);
cJSON *optionInfo = cJSON_CreateString(option);
cJSON_AddStringToObject(root, "option", option);
// 将封装的json转换成字符串,测试打印
char *all_data = cJSON_Print(root); // 将JSON对象转换为格式化字符串
puts(all_data);
// 转存数据
char *str = (char *)malloc(strlen(all_data) + 1); // 为新字符串分配内存,注意+1用于存储字符串结束符
strcpy(str, all_data); // 复制字符串
send(s_sockfd, str, strlen(all_data) + 1, 0);
// 清理内存
cJSON_Delete(root); // 删除根JSON对象,释放内存
free(all_data); // 释放cJSON_Print分配的内存
puts("打包成功");
return str; // 返回封装好的JSON字符串
}
main.c
#include "head.h"
// 宏定义id地址
#define IP_PATH "192.168.118.129"
// 宏定义端口号
#define PORT 8888
int main(int argc, char const *argv[])
{
// 创建线程id
pthread_t tid1;
// 设置线程分离状态
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 1.创建socket
int s_sockfd = socket_init(IP_PATH, PORT);
if (s_sockfd == -1)
{
printf("main:socket创建失败\n");
return -1;
}
puts("main:socket创建成功");
// 2.循环监听客户端连接
while (1)
{
// 2.1 建立连接
int c_sockfd = socket_accept(s_sockfd);
if (c_sockfd == -1)
{
printf("main:socket_accept建立连接失败\n");
return -1;
}
puts("main:socket_accept建立连接成功");
// 2.2 创建线程
pthread_create(&tid1, &attr, register_service, &c_sockfd);
}
// 销毁线程
pthread_attr_destroy(&attr);
return 0;
}
sql.h
#ifndef __SQL_H
#define __SQL_H
#include "head.h"
// 数据库连接函数
MYSQL *mysql_connect();
// 数据库查询函数
MYSQL_RES *mysql_query_m(MYSQL *conn, char *sql);
// 数据库增、删、改
int mysql_update(MYSQL *conn, char *sql);
// 数据库输出函数
void mysql_print(MYSQL_RES *res);
// 数据库断开连接函数
void mysql_disconnect(MYSQL *conn);
// 查看个人信息
int check_info(char *sql,char *buf);
// 修改个人信息函数
int modify_info(char *sql);
// 修改密码
int modify_pass(char *sql);
// 添加好友(执行没有输出结果的sql语句均可)
int add_friend(char *sql);
// 查询信息执行函数(一般查询通用)
int query_info(char *sql,char *buf);
// 查询某条信息是否存在
int query_info_is(char *sql);
//获取某一个字段的值
char *get_field_value(char *sql,char *buf);
// 查询聊天记录
int query_chat(char *sql,char *buf);
#endif
sql.c
#include "sql.h"
// 数据库连接函数
MYSQL *mysql_connect()
{
// 1.初始化数据库连接对象
MYSQL *conn = mysql_init(NULL);
if (NULL == conn)
{
perror("数据库连接mysql_connect:mysql_init失败");
return NULL;
}
puts("数据库连接mysql_connect:mysql_init 初始化成功!");
// 2.连接数据库 ip地址 用户名 密码 数据库名 端口号 认证方式 标志位
conn = mysql_real_connect(conn, "192.168.118.129", "sgc", "sgc", "chat", 0, NULL, 0);
if (NULL == conn)
{
perror("数据库连接mysql_connect:mysql_real_connect失败");
return NULL;
}
puts("数据库连接mysql_connect:mysql_real_connect 连接成功!");
// 设置客户端连接字符集为 UTF - 8
if (mysql_set_character_set(conn, "utf8mb4") != 0)
{
fprintf(stderr, "数据库连接mysql_set_character_set() failed: %s\n", mysql_error(conn));
mysql_close(conn);
return NULL;
}
return conn;
}
// 数据库查询并输出函数
MYSQL_RES *mysql_query_m(MYSQL *conn, char *sql)
{
// 1.执行sql语句
int ret = mysql_query(conn, sql);
if (0 != ret)
{
perror("数据库查询mysql_query:mysql_query失败");
return NULL;
}
puts("数据库查询mysql_query:mysql_query 执行成功!");
// 2.获取查询结果
MYSQL_RES *res = mysql_store_result(conn);
if (NULL == res)
{
puts("数据库查询mysql_query:mysql_store_result失败,无匹配数据");
return NULL;
}
// 3.获取结果集的行数
if (0 == mysql_num_rows(res))
{
puts("数据库查询mysql_query:mysql_num_rows 无匹配数据");
return NULL;
}
puts("数据库查询mysql_query:mysql_store_result 获取结果成功!");
// 3.返回结果
return res;
}
// 数据库输出函数
void mysql_print(MYSQL_RES *res)
{
puts("数据库输出函数mysql_print:开始输出结果!");
// 1.获取结果集中的字段数
int num_fields = mysql_num_fields(res);
// 2.获取结果集中的行数
int num_rows = mysql_num_rows(res);
// 3.获取结果集中的字段信息
MYSQL_FIELD *field = mysql_fetch_fields(res);
// 4.获取结果集中的每一行数据
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != NULL)
{
for (int i = 0; i < num_fields; i++)
{
}
}
puts("数据库输出函数mysql_print:mysql_fetch_row 获取每一行数据成功!");
}
// 数据库增删改
int mysql_update(MYSQL *conn, char *sql)
{
// 1.执行sql语句
int ret = mysql_query(conn, sql);
if (0 != ret)
{
perror("数据库增删改mysql_update:mysql_query 失败");
return -1;
}
puts("数据库增删改mysql_update:mysql_query 执行成功!");
// 3.返回结果
return 0;
}
// 数据库断开连接函数
void mysql_disconnect(MYSQL *conn)
{
// 1.断开连接
mysql_close(conn);
puts("数据库断开连接mysql_disconnect:mysql_close 断开连接成功!");
}
// 查看个人信息
int check_info(char *sql, char *buf)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("查看个人信息check_info:mysql_connect 连接失败");
return -1;
}
// 2.查询数据库
MYSQL_RES *res = mysql_query_m(conn, sql);
if (NULL == res)
{
puts("查看个人信息check_info:mysql_query_m 查询失败");
return -1;
}
// 将结果拼接到buf中
// 1.获取结果集中的字段数
int num_fields = mysql_num_fields(res);
// 2.获取结果集中的行数
int num_rows = mysql_num_rows(res);
// 3.获取结果集中的字段信息
MYSQL_FIELD *field = mysql_fetch_fields(res);
// 4.获取结果集中的每一行数据
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != NULL) // 遍历每一行数据
{
for (int i = 0; i < num_fields; i++) // 遍历每一行数据的每一个字段
{
printf("%s---%s\t", field[i].name, row[i]);
// 将字段名和字段值拼接到buf中
sprintf(buf, "%s%s---%s\t\n", buf, field[i].name, row[i]);
}
}
// 3.断开连接
mysql_disconnect(conn);
return 0;
}
// 修改个人信息函数
int modify_info(char *sql)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("修改个人信息modify_info:mysql_connect 连接失败");
return -1;
}
// 2.修改数据库
int ret = mysql_update(conn, sql);
if (0 != ret)
{
puts("修改个人信息modify_info:mysql_update 修改失败");
}
// 3.断开连接
mysql_disconnect(conn);
return 0;
}
// 修改密码
int modify_pass(char *sql)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("修改密码modify_pass:mysql_connect 连接失败");
return -1;
}
// 2.修改数据库
int ret = mysql_update(conn, sql);
if (0 != ret)
{
puts("修改密码modify_pass:mysql_update 修改失败");
}
// 3.断开连接
mysql_disconnect(conn);
return 0;
}
// 添加好友
int add_friend(char *sql)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("添加好友add_friend:mysql_connect 连接失败");
return -1;
}
// 2.添加好友
int ret = mysql_update(conn, sql);
if (0 != ret)
{
puts("添加好友add_friend:mysql_update 添加失败");
return -1;
}
// 3.断开连接
mysql_disconnect(conn);
return 0;
}
// 查询信息执行函数
int query_info(char *sql, char *buf)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("查询信息query_info:mysql_connect 连接失败");
return -1;
}
// 2.查询数据库
MYSQL_RES *res = mysql_query_m(conn, sql);
if (NULL == res)
{
puts("查询信息query_info:mysql_query_m 查询失败");
return -1;
}
// 3.将结果拼接到buf中
// 1.获取结果集中的字段数
int num_fields = mysql_num_fields(res);
// 2.获取结果集中的行数
int num_rows = mysql_num_rows(res);
// 3.获取结果集中的字段信息
MYSQL_FIELD *field = mysql_fetch_fields(res);
// 4.获取结果集中的每一行数据
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != NULL) // 遍历每一行数据
{
for (int i = 0; i < num_fields; i++) // 遍历每一行数据的每一个字段
{
printf("%s---%s\t", field[i].name, row[i]);
// 将字段名和字段值拼接到buf中
sprintf(buf, "%s %s\t\n", buf, row[i]);
}
}
// 3.断开连接
mysql_disconnect(conn);
return 0;
}
// 查询某条信息是否存在
int query_info_is(char *sql)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("查询某条信息是否存在query_info_is:mysql_connect 连接失败");
return -1;
}
// 执行 SQL 查询语句
if (mysql_query(conn, sql) != 0)
{
// 若查询执行失败,输出失败的错误信息
fprintf(stderr, "mysql_query() 执行查询失败: %s\n", mysql_error(conn));
return -1;
}
// 获取查询结果集
MYSQL_RES *res = mysql_store_result(conn);
// 检查结果集是否获取成功
if (res == NULL)
{
// 使用 mysql_field_count(conn) 来判断是正常的无结果集查询还是出现了错误
if (mysql_field_count(conn) == 0)
{
// 若返回 0,说明查询没有返回结果集(如 INSERT、UPDATE 等操作)
fprintf(stderr, "查询未返回结果集。\n");
}
else
{
// 否则表示获取结果集时出现错误,输出错误信息
fprintf(stderr, "mysql_store_result() 获取结果集失败: %s\n", mysql_error(conn));
}
return -1;
}
// 获取结果集中的行数
int row_count = mysql_num_rows(res);
// 释放结果集占用的内存,避免内存泄漏
mysql_free_result(res);
// 返回结果集的行数
return row_count;
}
// 获取某一个字段的值
char *get_field_value(char *sql, char *buf)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("获取某一个字段的值get_field_value:mysql_connect 连接失败");
return NULL;
}
// 2.查询数据库
MYSQL_RES *res = mysql_query_m(conn, sql);
if (NULL == res)
{
puts("获取某一个字段的值get_field_value:mysql_query_m 查询失败");
// 4.断开连接
mysql_disconnect(conn);
return NULL;
}
// 3.判断结果是否为空
if (0 == mysql_num_rows(res))
{
puts("获取某一个字段的值get_field_value:mysql_num_rows 查询结果为空");
// 4.断开连接
mysql_disconnect(conn);
return NULL;
}
// 4.获取结果集中的每一行数据
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != NULL) // 遍历每一行数据
{
for (int i = 0; i < mysql_num_fields(res); i++) // 遍历每一行数据的每一个字段
{
// 将字段值拼接到buf中
sprintf(buf, "%s", row[i]);
return buf;
}
}
}
// 查询聊天记录
int query_chat(char *sql, char *buf)
{
// 1.连接数据库
MYSQL *conn = mysql_connect();
if (NULL == conn)
{
puts("查询聊天记录query_info:mysql_connect 连接失败");
return -1;
}
// 2.查询数据库
MYSQL_RES *res = mysql_query_m(conn, sql);
if (NULL == res)
{
puts("查询聊天记录query_info:mysql_query_m 查询失败");
return -1;
}
// 3.将结果拼接到buf中
// 1.获取结果集中的字段数
int num_fields = mysql_num_fields(res);
// 2.获取结果集中的行数
int num_rows = mysql_num_rows(res);
// 3.获取结果集中的字段信息
MYSQL_FIELD *field = mysql_fetch_fields(res);
// 4.获取结果集中的每一行数据
MYSQL_ROW row;
int n = 1;
while ((row = mysql_fetch_row(res)) != NULL) // 遍历每一行数据
{
for (int i = 0; i < num_fields; i++) // 遍历每一行数据的每一个字段
{
printf("%s---%s\t", field[i].name, row[i]);
if (n == 1)
{
// 将字段名和字段值拼接到buf中
sprintf(buf, "%s %s", buf, row[i]);
}
else if (n == 2)
{
// 将字段名和字段值拼接到buf中
sprintf(buf, "%s---%s", buf, row[i]);
}
else if (n == 3)
{
// 将字段名和字段值拼接到buf中
sprintf(buf, "%s:%s\n", buf, row[i]);
n = 1;
continue;
}
n++;
}
}
// 3.断开连接
mysql_disconnect(conn);
return 0;
}
TCPserver.h
#ifndef __THREAD_POOL_H
#define __THREAD_POOL_H
// 引入头文件
#include "head.h"
// 定义一个套接字数据,存储所有连接的客户端
typedef struct sockaddr_in SockAddrIn;
// 定义一个结构体,存储客户端的信息最大存储10个
//int sockfdNUM[10] = {0};
//用户注册登录的结构体
typedef struct
{
char option[2];
char username[20];
char password[20];
} __attribute__((packed)) User;
// 根据ip地址和端口号初始化socket
int socket_init(char *ip, int port);
// 监听客户端,建立连接
int socket_accept(int listenfd);
// 注册登录服务函数
void * register_service(void *args);
// 登录后的个人信息界面服务函数
int login_service(void *args);
// 登陆主界面用户选择
int login_main(void *args);
// 联系人服务函数
int contact_service(void *args);
// 好友申请处理函数
int friend_apply_service(int c_socket);
// 聊天界面函数
int chat_service(void *args);
// 私聊界面函数
int private_chat_service(void *args);
// 公屏聊天界面函数
int public_chat_service(void *args);
#endif
TCPserver.c
#include "TCPserver.h"
int sockfdNUM[40] = {0};
typedef struct
{
int uid;
int sockfd;
} UID_t;
typedef struct
{
int uid;
int sockfd;
} CHAT_t;
UID_t uid[40] = {0};
CHAT_t chat[20] = {0};
CHAT_t g_chat[20] = {0};
// 根据ip地址和端口号初始化socket
int socket_init(char *ip, int port)
{
puts("进入初始化");
// 1.创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("初始化:socket失败");
return -1;
}
puts("初始化:socket成功");
// 2.绑定地址
SockAddrIn serverAddr;
// ipv4协议
serverAddr.sin_family = AF_INET;
// 端口
serverAddr.sin_port = htons(port);
// ip地址
serverAddr.sin_addr.s_addr = inet_addr(ip);
// 3.绑定地址
int ret = bind(sockfd, (SockAddr *)&serverAddr, sizeof(serverAddr));
if (-1 == ret)
{
perror("初始化:bind失败");
return -1;
}
puts("初始化:bind成功");
// 4.监听
ret = listen(sockfd, 10);
if (-1 == ret)
{
perror("初始化:listen失败");
}
puts("初始化:listen成功");
// 返回监听的套接字
return sockfd;
}
// 根据监听,建立连接
int socket_accept(int listenfd)
{
puts("进入监听,连接");
// 阻塞等待客户端的连接
int c_socket = accept(listenfd, NULL, NULL);
if (-1 == c_socket)
{
perror("监听,连接:accept失败");
return -1;
}
puts("监听,连接:accept成功");
// 存储客户端套接字描述符
for (size_t i = 0; i < 10; i++)
{
if (0 == sockfdNUM[i])
{
sockfdNUM[i] = c_socket;
puts("监听,连接:accept成功");
break;
}
}
// 测试打印
printf("监听,连接:c_socket=%d\n", c_socket);
// 获取客户端的ip地址和端口号
SockAddrIn clientAddr;
socklen_t len = sizeof(clientAddr);
int ret = getpeername(c_socket, (SockAddr *)&clientAddr, &len);
if (-1 == ret)
{
perror("监听,连接:getpeername失败");
return -1;
}
puts("监听,连接:getpeername成功");
printf("监听,连接:client ip=%s, port=%d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
// 给客户端做出响应---发送连接成功的标识
char *msg = "连接服务器成功";
send(c_socket, msg, strlen(msg), 0);
// 返回客户端的套接字
return c_socket;
}
// 注册登录服务函数
void *register_service(void *args)
{
puts("进入注册登录服务函数");
// // 创建互斥锁
// pthread_mutex_t mutex;
// // 初始化互斥锁
// pthread_mutex_init(&mutex, NULL);
// 获取客户端的套接字
int c_socket = *(int *)args;
// 测试打印
printf("注册登录服务函数:c_socket=%d\n", c_socket);
// 接收客户端的数据
char buf[1024] = {0};
// 接收json数据
char jsonString[1024] = {0};
User *user;
ssize_t n = -1;
// 清理缓冲区
memset(buf, 0, sizeof(buf));
// 接收客户端的数据
int stat = 0;
recv(c_socket, &stat, sizeof(stat), 0);
printf("%d\n", stat);
if (stat == 1)
{
// 进入私聊服务函数,创建线程
private_chat_service(&c_socket);
goto end;
}
else if (stat == 2)
{
// 进入公屏聊天服务函数,创建线程
public_chat_service(&c_socket);
goto end;
}
while (1)
{
printf("注册登录服务函数c_socket:%d\n", c_socket);
n = recv(c_socket, jsonString, sizeof(jsonString), 0);
// 解析json数据
user = (User *)login_user(jsonString);
if (-1 == n) // 接收失败
{
perror("注册登录服务函数:recv失败");
break;
}
else if (0 == n) // 客户端关闭连接
{
printf("注册登录服务函数:client %d closed\n", c_socket);
break;
}
else // 接收成功
{
printf("注册登录服务函数:recv成功\n");
printf("注册登录服务函数:recv name=%s , pass=%s\n", user->username, user->password);
printf("注册登录服务函数:recv option=%s\n", user->option);
}
// 判断用户的选择
if (strcmp(user->option, "1") == 0)
{
// 加锁
//pthread_mutex_lock(&mutex);
// 调用sql.c的数据库连接函数,连接数据库
MYSQL *conn = mysql_connect();
char sql[128] = {0};
// 拼接sql语句
// 注册用户
sprintf(sql, "insert into user(username,userpass) values('%s','%s');", user->username, user->password);
puts(sql);
// 执行sql语句
if (-1 == mysql_update(conn, sql))
{
// 注册失败
// 发送消息给客户端
send(c_socket, "注册失败", strlen("注册失败"), 0);
// 关闭数据库
mysql_disconnect(conn);
continue;
}
// 注册成功,返回用户的UID
mysql_query(conn, "SELECT * FROM user ORDER BY uid DESC;");
// 获取结果集
MYSQL_RES *res = mysql_store_result(conn);
// 获取结果集的行数
int row = mysql_num_rows(res);
// 获取结果集的第一行第一列的数据
MYSQL_ROW row_data = mysql_fetch_row(res);
// 获取UID
int uid = atoi(row_data[0]);
printf("注册登录服务函数:uid=%d\n", uid);
// 拼接UID和密码
sprintf(buf, "注册成功,你的UID是:%d", uid);
// 发送UID给客户端
send(c_socket, buf, sizeof(buf), 0);
// 拼接插入个人信息的sql语句
// 清空sql
memset(sql, 0, sizeof(sql));
sprintf(sql, "insert into user_info(info_uid,info_name) values('%d','%s');", uid, user->username);
// 执行sql语句
if (-1 == mysql_update(conn, sql))
{
// 注册失败
// 发送消息给客户端
send(c_socket, "注册失败", strlen("注册失败"), 0);
// 关闭数据库
mysql_disconnect(conn);
continue;
}
// 关闭数据库
mysql_disconnect(conn);
// 解锁
//pthread_mutex_unlock(&mutex);
continue;
}
else if (strcmp(user->option, "2") == 0)
{
// 加锁
//pthread_mutex_lock(&mutex);
// 检测UID和密码是否正确
// 调用sql.c的数据库连接函数,连接数据库
MYSQL *conn = mysql_connect();
char sql[128] = {0};
// 拼接sql语句
// 检测UID和密码是否正确
// 清空sql
memset(sql, 0, sizeof(sql));
sprintf(sql, "select * from user where uid='%d' and userpass='%s';", atoi(user->username), user->password);
puts(sql);
// 执行sql语句
if (NULL == mysql_query_m(conn, sql))
{
// 登录失败
// 发送消息给客户端
send(c_socket, "登录失败,uid或密码不正确", strlen("登录失败,uid或密码不正确"), 0);
// 关闭数据库
mysql_disconnect(conn);
continue;
}
// 检查该UID是否已经登录
// 清空sql
memset(sql, 0, sizeof(sql));
sprintf(sql, "select * from user where uid='%d' and state='0';", atoi(user->username));
puts(sql);
// 执行sql语句
if (NULL == mysql_query_m(conn, sql))
{
// 登录失败
// 发送消息给客户端
send(c_socket, "该用户处于在线状态", strlen("该用户处于在线状态"), 0);
// 关闭数据库
mysql_disconnect(conn);
continue;
}
// 登录成功
// 发送消息给客户端
send(c_socket, "登录成功", strlen("登录成功"), 0);
// 关闭数据库
mysql_disconnect(conn);
// 创建线程
login_main(&c_socket);
// 解锁
//pthread_mutex_unlock(&mutex);
break;
}
else if (strcmp(buf, "q") == 0) // 退出
{
// 退出
return 0;
}
// 清空缓冲区
memset(&user, 0, sizeof(user));
memset(buf, 0, sizeof(buf));
// 释放内存
free(user);
user = NULL;
}
end:
// 销毁互斥锁
//pthread_mutex_destroy(&mutex);
// 关闭客户端的套接字
close(c_socket);
}
// 登陆主界面用户选择
int login_main(void *args)
{
char ch;
puts("进入用户主界面");
UID_t tmp_uid;
int c_socket = *(int *)args;
// 测试打印
printf("用户主界面:c_socket=%d\n", c_socket);
// 接收客户端登录后发送的UID
recv(c_socket, &tmp_uid.uid, sizeof(tmp_uid.uid), 0);
// if (strlen(tmp_uid.uid) == 0)
// {
// /* code */
// }
printf("用户主界面:uid=%d\n", tmp_uid.uid);
// 将该UID的用户设置为登录状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='1' where uid='%d';", tmp_uid.uid);
puts(sql);
// 执行sql语句
add_friend(sql);
printf("用户主界面:uid=%d\n", tmp_uid.uid);
// 接收客户端的套接字
tmp_uid.sockfd = c_socket;
int falg = 1;
// 存储登录的客户端UID和套接字
for (size_t i = 0; i < 20; i++)
{
if (0 == uid[i].uid)
{
uid[i] = tmp_uid;
falg = 0;
break;
}
}
if (1 == falg)
{
printf("用户主界面:uid数组已满\n");
}
// 接收客户端的数据
char buf[1024] = {0};
ssize_t n = -1;
while (1)
{
char option[50] = {0};
n = recv(c_socket, option, sizeof(option), 0);
if (-1 == n) // 接收失败
{
perror("用户主界面:recv失败");
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", tmp_uid.uid);
puts(sql);
// 执行sql语句
add_friend(sql);
break;
}
else if (0 == n) // 客户端关闭连接
{
printf("用户主界面:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", tmp_uid.uid);
puts(sql);
// 执行sql语句
add_friend(sql);
break;
}
else // 接收成功
{
printf("用户主界面:recv成功\n");
printf("用户主界面:recv 选择=%s\n", option);
}
// 判断用户的选择
if (strcmp(option, "1") == 0) // 查看个人信息
{
// 创建线程,进入个人信息主页面
login_service(&c_socket);
}
else if (strcmp(option, "2") == 0) // 联系人
{
// 创建线程,进入联系人主页面
contact_service(&c_socket);
}
else if (strcmp(option, "3") == 0) // 聊天
{
// 创建线程,进入聊天主页面
chat_service(&c_socket);
}
else if (strcmp(option, "q") == 0) // 退出
{
// 关闭客户端的套接字
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", tmp_uid.uid);
puts(sql);
// 执行sql语句
add_friend(sql);
puts("登录主界面退出");
close(c_socket);
puts("c_socket:套接字关闭");
return 0;
}
// 清空缓冲区
memset(buf, 0, sizeof(buf));
}
// 情况sql
memset(sql, 0, sizeof(sql));
sprintf(sql, "update user set state='0' where uid='%d';", tmp_uid.uid);
puts(sql);
// 执行sql语句
add_friend(sql);
puts("登录主界面退出");
close(c_socket);
puts("c_socket:套接字关闭");
return 0;
}
// 登录后的个人信息界面服务函数
int login_service(void *args)
{
puts("进入个人信息界面服务函数");
int c_socket = *(int *)args;
// 获取登录用户的UID
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 接收客户端的数据
char buf[1024] = {0};
ssize_t n = -1;
while (1)
{
n = recv(c_socket, buf, sizeof(buf), 0);
if (-1 == n) // 接收失败
{
perror("个人信息界面服务函数:recv失败");
printf("个人信息界面服务函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
break;
}
else if (0 == n) // 客户端关闭连接
{
printf("个人信息界面服务函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
break;
}
else // 接收成功
{
printf("个人信息界面服务函数:recv成功\n");
printf("个人信息界面服务函数:recv 选择=%s\n", buf);
}
// 判断用户的选择
if (strcmp(buf, "1") == 0) // 查看个人信息
{
// 查看个人信息
// 根据套接字获取UID
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "SELECT * FROM user_info WHERE info_uid='%d';", user_id);
puts(sql);
// 调用查询个人信息的函数
if (check_info(sql, buf) != 0)
{
// 发送消息给客户端
send(c_socket, "查看个人信息失败", strlen("查看个人信息失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, buf, strlen(buf), 0);
continue;
}
else if (strcmp(buf, "2") == 0) // 修改个人信息
{
// 修改个人信息
// 根据套接字获取UID
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 拼接sql语句
char sql[512] = {0};
// 接收客户端传来的数据
recv(c_socket, buf, sizeof(buf), 0);
// 拼接sql语句
sprintf(sql, "%s WHERE info_uid='%d';", buf, user_id);
puts(sql);
// 调用修改个人信息的函数
if (modify_info(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "修改个人信息失败", strlen("修改个人信息失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, "修改个人信息成功", strlen("修改个人信息成功"), 0);
continue;
}
else if (strcmp(buf, "3") == 0) // 修改密码
{
// 修改密码
// 根据套接字获取UID
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 拼接sql语句
char sql[512] = {0};
// 接收客户端传来的数据
recv(c_socket, buf, sizeof(buf), 0);
// 拼接sql语句
sprintf(sql, "%s'%d';", buf, user_id);
puts(sql);
// 调用修改密码的函数
if (modify_pass(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "修改密码失败", strlen("修改密码失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, "修改密码成功", strlen("修改密码成功"), 0);
continue;
}
else if (strcmp(buf, "q") == 0) // 退出
{
return 0;
}
// 清空缓冲区
memset(buf, 0, sizeof(buf));
}
puts("个人信息界面服务函数:退出");
}
// 联系人服务函数
int contact_service(void *args)
{
puts("进入联系人函数");
int c_socket = *(int *)args;
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 接收客户端的数据
char buf[1024] = {0};
ssize_t n = -1;
while (1)
{
n = recv(c_socket, buf, sizeof(buf), 0);
if (-1 == n) // 接收失败
{
perror("联系人函数:recv失败");
printf("个人信息界面服务函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
break;
}
else if (0 == n) // 客户端关闭连接
{
printf("联系人函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
break;
}
else // 接收成功
{
printf("联系人函数:recv成功\n");
printf("联系人函数:recv 选择===%s\n", buf);
}
// 判断用户的选择
if (strcmp(buf, "1") == 0) // 查看好友列表
{
// 查看好友列表
// 拼接sql语句
char sql[512] = {0};
sprintf(sql, "SELECT * FROM friends WHERE id='%d';", user_id);
puts(sql);
// 调用sql函数
if (check_info(sql, buf) != 0)
{
// 发送消息给客户端
send(c_socket, "查看好友列表失败", strlen("查看好友列表失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, buf, strlen(buf), 0);
continue;
}
else if (strcmp(buf, "2") == 0) // 添加好友
{
int id = 0;
// 接收客户端传来的数据
recv(c_socket, &id, sizeof(id), 0);
// 获取自己的昵称
char nick_name[50] = {0};
// 拼接sql语句
char sql[512] = {0};
sprintf(sql, "SELECT username FROM user WHERE uid='%d';", user_id);
puts(sql);
// 调用查询个人信息的函数
if (query_info(sql, nick_name) != 0)
{
// 发送消息给客户端
send(c_socket, "查看该uid信息失败", strlen("查看uid信息失败"), 0);
continue;
}
printf("联系人函数:nick_name:%s\n", nick_name);
// 清空sql缓冲区
memset(sql, 0, sizeof(sql));
// 拼接sql语句
sprintf(sql, "INSERT INTO Friend_application(uid,f_uid,f_name) VALUES('%d','%d','%s');", id, user_id, nick_name);
puts(sql);
// 调用添加好友的函数
if (add_friend(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "好友申请发送失败", strlen("好友申请发送失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, "好友申请发送成功", strlen("好友申请发送成功"), 0);
continue;
}
else if (strcmp(buf, "3") == 0) // 删除好友
{
// 删除好友
// 接收客户端传来的数据
recv(c_socket, buf, sizeof(buf), 0);
// 拼接sql语句
char sql[512] = {0};
sprintf(sql, "DELETE FROM friends WHERE id='%d' AND Friends_id='%d';", user_id, atoi(buf));
puts(sql);
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "删除好友失败", strlen("删除好友失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, "删除好友成功", strlen("删除好友成功"), 0);
continue;
}
else if (strcmp(buf, "4") == 0) // 好友申请
{
friend_apply_service(c_socket);
}
else if (strcmp(buf, "q") == 0) // 退出
{
// 创建线程,返回登陆后主界面
return 0;
}
// 清空缓冲区
memset(buf, 0, sizeof(buf));
}
puts("联系人界面退出");
}
// 好友申请处理函数
int friend_apply_service(int c_socket)
{
puts("进入好友申请处理函数");
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 循环接收客户端数据
char buf[1024] = {0};
ssize_t n = -1;
while (1)
{
n = recv(c_socket, buf, sizeof(buf), 0);
if (-1 == n) // 接收失败
{
perror("好友申请处理函数:recv失败");
printf("个人信息界面服务函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
return -1;
}
else if (0 == n) // 客户端关闭连接
{
printf("好友申请处理函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
return -1;
}
else // 接收成功
{
printf("好友申请处理函数:recv成功\n");
printf("好友申请处理函数:recv 选择===%s\n", buf);
}
// 判断用户的选择
if (strcmp(buf, "1") == 0) // 查看好友申请
{
// 查看好友申请
// 拼接sql语句
char sql[512] = {0};
sprintf(sql, "SELECT f_uid,f_name FROM Friend_application WHERE uid='%d';", user_id);
puts(sql);
// 调用sql函数
if (check_info(sql, buf) != 0)
{
// 发送消息给客户端
send(c_socket, "查看好友申请失败", strlen("查看好友申请失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, buf, strlen(buf), 0);
continue;
}
else if (strcmp(buf, "2") == 0) // 同意好友申请
{
// 同意好友申请
// 接收客户端传来的数据
int id = 0;
recv(c_socket, &id, sizeof(id), 0);
// 拼接sql语句
char sql[512] = {0};
// 根据id删除好友申请
sprintf(sql, "DELETE FROM Friend_application WHERE uid='%d' AND f_uid='%d';", user_id, id);
puts(sql);
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "同意好友申请失败", strlen("同意好友申请失败"), 0);
continue;
}
// 清空sql缓冲区
memset(sql, 0, sizeof(sql));
// 根据id查询好友昵称
char nick_name[50] = {0};
// 拼接sql语句
sprintf(sql, "SELECT username FROM user WHERE uid='%d';", id);
puts(sql);
// 调用查询个人信息的函数
if (query_info(sql, nick_name) != 0)
{
// 发送消息给客户端
send(c_socket, "查看该uid信息失败", strlen("查看uid信息失败"), 0);
continue;
}
// 清空sql缓冲区
memset(sql, 0, sizeof(sql));
// 拼接sql语句,添加好友
sprintf(sql, "INSERT INTO friends(id,Friends_id,Friends_name) VALUES('%d','%d','%s');", id, user_id, nick_name);
puts(sql);
// 调用添加好友的函数,没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "添加好友失败", strlen("添加好友失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, "添加好友成功", strlen("添加好友成功"), 0);
continue;
}
else if (strcmp(buf, "3") == 0) // 拒绝好友申请
{
// 拒绝好友申请
// 接收客户端传来的数据
int id = 0;
recv(c_socket, &id, sizeof(id), 0);
// 拼接sql语句
char sql[512] = {0};
// 根据id删除好友申请
sprintf(sql, "DELETE FROM Friend_application WHERE uid='%d' AND f_uid='%d';", user_id, id);
puts(sql);
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
// 发送消息给客户端
send(c_socket, "拒绝好友申请失败", strlen("拒绝好友申请失败"), 0);
continue;
}
// 发送消息给客户端
send(c_socket, "拒绝好友申请成功", strlen("拒绝好友申请成功"), 0);
continue;
}
else if (strcmp(buf, "q") == 0) // 退出
{
return 0;
}
// 清空缓冲区
memset(buf, 0, sizeof(buf));
}
puts("好友申请页面");
}
// 聊天界面函数
int chat_service(void *args)
{
puts("进入聊天界面函数");
int c_socket = *(int *)args;
int user_id = 0;
for (size_t i = 0; i < 20; i++)
{
if (c_socket == uid[i].sockfd)
{
user_id = uid[i].uid;
break;
}
}
// 循环接收客户端数据
char buf[1024] = {0};
ssize_t n = -1;
while (1)
{
puts("开始下一次接收");
n = recv(c_socket, buf, sizeof(buf), 0);
if (-1 == n) // 接收失败
{
perror("聊天界面函数:recv失败");
printf("个人信息界面服务函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
return 0;
}
else if (0 == n) // 客户端关闭连接
{
printf("聊天界面函数:client %d 关闭\n", c_socket);
// 将该UID的用户设置为离线状态
// 拼接sql语句
char sql[128] = {0};
sprintf(sql, "update user set state='0' where uid='%d';", user_id);
puts(sql);
// 执行sql语句
add_friend(sql);
return 0;
}
else // 接收成功
{
printf("聊天界面函数:recv成功\n");
printf("聊天界面函数:recv 选择===%s\n", buf);
}
// 判断用户的选择
if (strcmp(buf, "1") == 0) // 好友私聊
{
// 接收好友UID
int f_id = 0;
recv(c_socket, &f_id, sizeof(f_id), 0);
// 拼接sql语句
char sql[512] = {0};
// 查询有没有该好友
sprintf(sql, "SELECT * FROM friends WHERE (id='%d' AND Friends_id='%d') or (id='%d' AND Friends_id='%d');", user_id, f_id, f_id, user_id);
puts(sql);
// 调用查询信息是否存在的函数
if (query_info_is(sql) == 1)
{
printf("好友存在\n");
int i = 1;
// 发送消息给客户端
send(c_socket, &i, sizeof(i), 0);
continue;
}
else
{
printf("好友不存在\n");
int i = 0;
// 发送消息给客户端
send(c_socket, &i, sizeof(i), 0);
continue;
}
continue;
}
else if (strcmp(buf, "2") == 0) // 好友群聊
{
continue;
}
else if (strcmp(buf, "q") == 0) // 退出
{
return 0;
}
// 清空缓冲区
memset(buf, 0, sizeof(buf));
}
puts("聊天界面退出");
}
// 私聊界面函数
int private_chat_service(void *args)
{
puts("进入私聊函数");
// 接收客户端套接字
int c_socket = *(int *)args;
int f_socket = 0;
// 接收用户UID
int user_id, f_id;
recv(c_socket, &user_id, sizeof(user_id), 0);
// 存储该聊天用户的UID已经套接字
for (size_t i = 0; i < 20; i++)
{
if (chat[i].sockfd == 0)
{
chat[i].sockfd = c_socket;
chat[i].uid = user_id;
break;
}
}
printf("user_id:%d\n", user_id);
// 接收好友UID
recv(c_socket, &f_id, sizeof(f_id), 0);
// 根据好友UID获取好友套接字
for (size_t i = 0; i < 20; i++)
{
if (f_id == chat[i].uid)
{
f_socket = chat[i].sockfd;
break;
}
}
// 拼接sql语句,检测有没有和该好友的聊天记录
char sql[512] = {0};
sprintf(sql, "SELECT * FROM p_chat_history WHERE (a_uid='%d' OR b_uid='%d') AND (a_uid='%d' OR b_uid='%d');", user_id, user_id, f_id, f_id);
puts(sql);
// 调用查询信息是否存在的函数
int ret = query_info_is(sql);
printf("ret:%d\n", ret);
if (-1 == ret) // 查询为空,没有聊天记录
{
// 给客户端发送通知
send(c_socket, "暂无聊天记录", strlen("暂无聊天记录"), 0);
// 拼接sql语句,插入聊天记录
sprintf(sql, "INSERT INTO p_chat_history(a_uid,b_uid,content) VALUES('%d','%d','标识');", user_id, f_id);
puts(sql);
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
puts("插入聊天记录失败");
}
}
else // 查询不为空,有聊天记录
{
// 拼接sql语句,返回聊天记录
sprintf(sql, "SELECT f_uid,f_name,content FROM p_chat_history WHERE (a_uid='%d' OR b_uid='%d') AND (a_uid='%d' OR b_uid='%d') AND content != '标识';", user_id, user_id, f_id, f_id);
puts(sql);
char buf[2048] = {0};
// 查询聊天记录函数
if (query_chat(sql, buf) != 0)
{
strcpy(buf, "暂无聊天记录");
puts("查询聊天记录失败");
}
// 发送消息给客户端
send(c_socket, buf, sizeof(buf), 0);
}
int flag = 0;
char buf[2048] = {0};
ssize_t n = -1;
while (1)
{
// 获取自己的用户名
// 拼接对应的sql语句
// 清空sql
char name[20] = {0};
memset(sql, 0, sizeof(sql));
sprintf(sql, "SELECT username FROM user WHERE uid='%d';", user_id);
puts(sql);
get_field_value(sql, name);
puts(name);
// 清除缓冲区
memset(buf, 0, sizeof(buf));
n = recv(c_socket, buf, sizeof(buf), 0);
if (-1 == n) // 接收失败
{
perror("私聊函数:recv失败");
return 0;
}
else if (0 == n) // 客户端关闭连接
{
// 拼接sql语句,修改为不可聊天状态,将chat_stat修改成0
sprintf(sql, "UPDATE p_chat_history SET chat_stat = '0' WHERE (a_uid='%d' OR b_uid='%d') AND (a_uid='%d' OR b_uid='%d') AND content = '标识';", user_id, user_id, f_id, f_id);
puts(sql);
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
puts("私聊状态修改失败");
}
return 0;
}
else // 接收成功
{
printf("私聊函数:recv成功\n");
printf("私聊函数:recv 选择===%s\n", buf);
}
// 判断用户的选择
if (strcmp(buf, "quit") == 0) // 私聊
{
continue;
}
puts(buf);
// 清空sql
memset(sql, 0, sizeof(sql));
// 拼接sql语句,插入聊天记录
sprintf(sql, "INSERT INTO p_chat_history(a_uid,b_uid,f_uid,f_name,content) VALUES('%d','%d','%d','%s','%s');", user_id, f_id, f_id, name, buf);
puts(sql);
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
puts("插入聊天记录失败");
}
// 根据好友UID获取好友套接字
for (size_t i = 0; i < 20; i++)
{
if (f_id == chat[i].uid)
{
f_socket = chat[i].sockfd;
break;
}
}
printf("===============f_socket:%d\n", f_socket);
char tmp[2048] = {0};
// 拼接发送的消息
sprintf(tmp, "%d---%s:%s", user_id, name, buf);
// 给好友发送消息
send(f_socket, tmp, strlen(tmp), 0);
// 清除缓冲区
memset(buf, 0, sizeof(buf));
}
// 关闭自己的套接字
close(c_socket);
puts("私聊结束");
}
// 公屏聊天界面函数
int public_chat_service(void *args)
{
puts("进入公屏聊天函数");
// 接收客户端套接字
int c_socket = *(int *)args;
int f_socket = 0;
// 接收用户UID
int user_id;
recv(c_socket, &user_id, sizeof(user_id), 0);
// 存储该聊天用户的UID已经套接字
for (size_t i = 0; i < 20; i++)
{
if (g_chat[i].sockfd == 0)
{
g_chat[i].sockfd = c_socket;
g_chat[i].uid = user_id;
break;
}
}
printf("user_id:%d\n", user_id);
char buf[2048] = {0};
ssize_t n = -1;
char sql[512] = {0};
while (1)
{
// 获取自己的用户名
// 拼接对应的sql语句
// 清空sql
char name[20] = {0};
memset(sql, 0, sizeof(sql));
sprintf(sql, "SELECT username FROM user WHERE uid='%d';", user_id);
puts(sql);
get_field_value(sql, name);
puts(name);
n = recv(c_socket, buf, sizeof(buf), 0);
if (-1 == n) // 接收失败
{
perror("公屏聊天函数:recv失败");
return 0;
}
else if (0 == n) // 客户端关闭连接
{
// 调用没有返回值的sql执行函数
if (add_friend(sql) != 0)
{
puts("私聊状态修改失败");
}
return 0;
}
else // 接收成功
{
printf("私聊函数:recv成功\n");
printf("私聊函数:recv 选择===%s\n", buf);
}
// 判断用户的选择
if (strcmp(buf, "quit") == 0) // 私聊
{
continue;
}
puts(buf);
char tmp[2048] = {0};
// 拼接发送的消息
sprintf(tmp, "%d---%s:%s", user_id, name, buf);
// 获取所有进入聊天界面的套接字
for (size_t i = 0; i < 20; i++)
{
if (g_chat[i].sockfd != 0)
{
// 给好友发送消息
send(g_chat[i].sockfd, tmp, strlen(tmp), 0);
}
}
// 清除缓冲区
memset(buf, 0, sizeof(buf));
}
// 关闭自己的套接字
close(c_socket);
puts("公屏聊天结束");
}
makefile
SRCS = $(wildcard *.c) ./cJSON-master/cJSON.c
OBJS = $(patsubst *.c,*.o,$(SRCS))
CC = gcc
TARGET = app
LDFLAGS = -lpthread -lmysqlclient
.PHONY : clean
$(TARGET) : $(OBJS)
$(CC) $^ -o $@ $(LDFLAGS)
clean :
rm *.o
run :
./$(TARGET)
show :
echo $(SRCS) / $(OBJS)