一、项目概述
该聊天室服务器是一个基于TCP/IP协议的简单网络应用。它使用套接字(socket)进行网络通信,允许多个客户端同时连接到服务器,进行实时聊天。
本聊天室服务器支持以下功能:
- 用户注册与登录
- 群聊与私聊
- 查看历史聊天记录
- 查看当前聊天室成员
- 服务器使用多线程处理多个客户端连接,确保每个客户端都能独立地与服务器进行交互。
二、代码结构
代码主要包括以下几个部分:
头文件引入:包括标准输入输出、网络编程、多线程、时间、字符串操作等必要的头文件。
结构体定义:定义用户信息和聊天记录的结构体。
函数声明与实现:包括账号管理、消息处理、网络通信等功能的函数。
主函数:初始化服务器,监听端口,接受客户端连接,并创建线程处理每个连接。
三、代码详解
- 结构体定义
typedef struct xinxi {
char id[20]; // 每个账号唯一id
char passwd[20]; // 账号密码
char name[50]; // 账号昵称
int fd; // 存放客户端成功连接后accept产生的新的套接字
struct xinxi* next; // 下一条链表的首地址
} X;
typedef struct chat_record {
char id[20]; // 发送者ID
char msg[1024]; // 消息内容
time_t timestamp; // 发送时间
struct chat_record* next;
} ChatRecord;
X结构体用于存储用户信息,ChatRecord结构体用于存储聊天记录。
- 函数实现
(1)账号管理
create函数用于创建账号信息的头指针,并从文件中读取已注册的账号信息。Sign_in函数用于用户注册,将新账号信息添加到链表并保存到文件。Save_account函数用于将所有账号信息保存到文件。
(2)消息处理
Add_chat_record函数用于添加聊天记录,并将记录保存到文件。Save_chat_records函数用于将聊天记录文件中的记录追加到文件中。
(3)网络通信
handleclient函数是服务器处理客户端请求的主要函数。它接收客户端发送的消息,根据消息内容执行相应的操作(如登录、注册、群聊、私聊等),并将结果发送回客户端。
- 细节优化
在原始代码中,当查看历史聊天记录时,服务器会读取chat_records.txt文件的内容并直接发送给客户端。然而,如果聊天记录的每行都包含敏感信息(如用户ID的前10个字符是敏感数据),并且我们想要跳过这些数据,就需要对读取到的每一行进行处理。
以下是对handleclient函数中查看历史聊天记录部分的修改:
if (strcmp(shou, "history") == 0) {
FILE* fp = fopen("chat_records.txt", "r");
if (fp == NULL) {
char fa[1024];
strcpy(fa, "无历史记录\n");
send(fd, fa, strlen(fa), 0);
return;
}
char buffer[1024];
char processed_buffer[1024]; // 用于存储处理后的行内容
while (fgets(buffer, sizeof(buffer), fp)) {
// 跳过每行的前10个字符
strncpy(processed_buffer, buffer + 10, strlen(buffer) - 10);
// 去除可能的换行符
processed_buffer[strcspn(processed_buffer, "\n")] = 0;
send(fd, processed_buffer, strlen(processed_buffer), 0);
}
fclose(fp);
continue;
}