diff --git a/Clion/.idea/.gitignore b/Clion/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/Clion/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/Clion/.idea/Clion.iml b/Clion/.idea/Clion.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/Clion/.idea/Clion.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Clion/.idea/editor.xml b/Clion/.idea/editor.xml
new file mode 100644
index 0000000..633b554
--- /dev/null
+++ b/Clion/.idea/editor.xml
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Clion/.idea/misc.xml b/Clion/.idea/misc.xml
new file mode 100644
index 0000000..db293e8
--- /dev/null
+++ b/Clion/.idea/misc.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+ {}
+
\ No newline at end of file
diff --git a/Clion/.idea/modules.xml b/Clion/.idea/modules.xml
new file mode 100644
index 0000000..cf65081
--- /dev/null
+++ b/Clion/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Clion/.idea/vcs.xml b/Clion/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/Clion/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Clion/CMakeLists.txt b/Clion/CMakeLists.txt
new file mode 100644
index 0000000..599356d
--- /dev/null
+++ b/Clion/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.31)
+project(Clion C)
+
+set(CMAKE_C_STANDARD 11)
+
+add_executable(Clion main.c)
diff --git a/Clion/main.c b/Clion/main.c
new file mode 100644
index 0000000..4dd72fa
--- /dev/null
+++ b/Clion/main.c
@@ -0,0 +1,7 @@
+#include
+
+int main(void)
+{
+ printf("Hello, World!\n");
+ return 0;
+}
\ No newline at end of file
diff --git a/Clion/test.c b/Clion/test.c
new file mode 100644
index 0000000..ce0ecf2
--- /dev/null
+++ b/Clion/test.c
@@ -0,0 +1,10 @@
+//
+// Created by ZBright on 25-5-29.
+//
+#include
+
+int main()
+{
+ printf("Hello World\n");
+ return 0;
+}
\ No newline at end of file
diff --git a/Clion/test.exe b/Clion/test.exe
new file mode 100644
index 0000000..ac41184
Binary files /dev/null and b/Clion/test.exe differ
diff --git a/Code/Project_Client.c b/Code/Project_Client.c
new file mode 100644
index 0000000..e69de29
diff --git a/Code/Project_Server.c b/Code/Project_Server.c
new file mode 100644
index 0000000..e69de29
diff --git a/Code/cet.c b/Code/cet.c
new file mode 100644
index 0000000..c7939b6
--- /dev/null
+++ b/Code/cet.c
@@ -0,0 +1,54 @@
+#include
+#include
+#include /* See NOTES */
+#include
+#include
+#include
+#include
+
+#define OWNADDR "192.168.0.17" //我自己电脑的ip地址
+#define OWNPORT 10000 //我自己电脑的该程序的端口号
+
+#define SERVERADDR "192.168.0.114" //对方的服务器的IP地址
+#define SERVERPORT 20000 //对方的服务器的端口号
+
+int main()
+{
+ //1、买手机(建立套接字)
+ int socketfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(socketfd == -1)
+ {
+ printf("没钱了....,失败\n");
+ return -1;
+ }
+ //2、绑定自己的电话号码(绑定自己的IP地址 和端口号)
+ //定义一个IPV4结构体变量,初始化自己的IP地址和端口号
+ struct sockaddr_in ownAddr;
+ ownAddr.sin_family = AF_INET;/*地址族 IPV4*/
+ ownAddr.sin_port = htons(OWNPORT);//htons 将本地端口号转为网络端口号
+ ownAddr.sin_addr.s_addr = inet_addr(OWNADDR);//将本地IP地址转为网络IP地址
+
+ bind(socketfd, (struct sockaddr *)&ownAddr,sizeof(struct sockaddr_in));
+
+ //3、开始打电话(发起连接)
+ struct sockaddr_in serverAddr;
+ serverAddr.sin_family = AF_INET;/*地址族 IPV4*/
+ serverAddr.sin_port = htons(SERVERPORT); //htons 将本地端口号转为网络端口号
+ serverAddr.sin_addr.s_addr = inet_addr(SERVERADDR); //将本地IP地址转为网络IP地址
+
+ connect(socketfd,(struct sockaddr *)&serverAddr,sizeof(struct sockaddr_in));
+
+ //4、聊天
+ while(1)
+ {
+ printf("data:");
+ char buf[1024]={0};
+ scanf("%s",buf);
+ //发送数据
+ send(socketfd, buf, strlen(buf), 0);
+ }
+ //5、关闭
+ close(socketfd);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/Code/output/cet b/Code/output/cet
new file mode 100644
index 0000000..1453414
Binary files /dev/null and b/Code/output/cet differ
diff --git a/Code/ser.c b/Code/ser.c
new file mode 100644
index 0000000..efdec25
--- /dev/null
+++ b/Code/ser.c
@@ -0,0 +1,65 @@
+#include
+#include /* See NOTES */
+#include
+#include
+#include
+#include
+#include
+
+
+
+#define SERVER_ADDR "172.29.147.16" //服务器的IP地址
+#define SERVER_PORT 20000 //port 服务器的端口号
+
+
+int main()
+{
+ int ret;
+ //1、买手机(建立套接字)
+ int socketFd = socket(AF_INET, SOCK_STREAM, 0);
+ if(socketFd == -1){
+ perror("socket error");
+ exit(0);
+ }
+ //2、绑定自己的电话号码(绑定自己的IP地址和端口号)
+ //定义一个IPV4结构体变量,存储IP地址和端口号
+ struct sockaddr_in serverAddr;
+ serverAddr.sin_family = AF_INET ;//IPv4
+ serverAddr.sin_port = htons(SERVER_PORT);//16端口号 --本地端口号--网络端口号
+ serverAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR); //32IP地址 --本地IP--网络IP
+
+ ret = bind(socketFd, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_in));
+ if(ret == -1){
+ perror("bind error");
+ exit(0);
+ }
+ //3、设置铃声(设置监听)
+ ret = listen(socketFd, 20); //20表示同时连接上来的客户端的最大数量
+ if(ret == -1){
+ perror("listen error");
+ exit(0);
+ }
+ printf("阻塞等待新的客户端连接......\n");
+ //4、坐等电话(阻塞等待客户端的连接)
+ int newClientFd = accept(socketFd, NULL,NULL);
+ if(ret == -1){
+ perror("accept error");
+ exit(0);
+ }
+ //注意 accept函数的返回值 表示 新的客户端的文件描述符 ,后面与客户端通信 必须使用该文件描述符
+ printf("有新的客户端连接上来....\n");
+
+ //5、聊天 接收 数据
+ while(1)
+ {
+ char buf[1024]={0};
+ read(newClientFd,buf,sizeof(buf));
+ printf("buf:%s\n",buf);
+ }
+
+ //6、关闭 断开连接
+ close(socketFd);
+ close(newClientFd);
+
+ return 0;
+}
diff --git a/Project/client b/Project/client
new file mode 100644
index 0000000..3f5f29a
Binary files /dev/null and b/Project/client differ
diff --git a/Project/client.c b/Project/client.c
new file mode 100644
index 0000000..53d748a
--- /dev/null
+++ b/Project/client.c
@@ -0,0 +1,270 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define BUFFER_SIZE 1024
+#define SERVER_IP "127.0.0.1"
+#define PORT 8888
+
+int client_socket;
+pthread_t receive_thread;
+int running = 1;
+
+// 函数声明
+void *receive_messages(void *arg);
+void handle_signal(int sig);
+void login_register_menu();
+
+int main() {
+ struct sockaddr_in server_addr;
+
+ // 创建socket
+ client_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (client_socket == -1) {
+ perror("Socket creation failed");
+ exit(EXIT_FAILURE);
+ }
+
+ // 准备服务器地址
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(PORT);
+
+ // 将IPv4地址从点分十进制转换为二进制形式
+ if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
+ perror("Invalid address/ Address not supported");
+ exit(EXIT_FAILURE);
+ }
+
+ // 连接到服务器
+ if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
+ perror("Connection failed");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Connected to server.\n");
+
+ // 设置信号处理
+ signal(SIGINT, handle_signal);
+
+ // 创建接收消息的线程
+ if (pthread_create(&receive_thread, NULL, receive_messages, NULL) != 0) {
+ perror("Thread creation failed");
+ close(client_socket);
+ exit(EXIT_FAILURE);
+ }
+
+ // 登录/注册菜单
+ login_register_menu();
+
+ // 聊天循环
+ printf("\nWelcome to the chat! Type /help for commands.\n");
+ char message[BUFFER_SIZE];
+ while (running) {
+ memset(message, 0, BUFFER_SIZE);
+ fgets(message, BUFFER_SIZE - 1, stdin);
+
+ // 移除换行符
+ size_t len = strlen(message);
+ if (len > 0 && message[len - 1] == '\n') {
+ message[len - 1] = '\0';
+ }
+
+ // 检查是否是退出命令
+ if (strcmp(message, "/quit") == 0) {
+ running = 0;
+ break;
+ }
+
+ // 发送消息到服务器
+ if (send(client_socket, message, strlen(message), 0) == -1) {
+ perror("Send failed");
+ running = 0;
+ }
+ }
+
+ // 等待接收线程结束
+ pthread_join(receive_thread, NULL);
+
+ // 关闭socket
+ close(client_socket);
+ printf("Disconnected from server.\n");
+
+ return 0;
+}
+
+void *receive_messages(void *arg) {
+ char buffer[BUFFER_SIZE];
+ int bytes_received;
+
+ while (running) {
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
+
+ if (bytes_received <= 0) {
+ // 服务器断开连接
+ printf("Server disconnected.\n");
+ running = 0;
+ break;
+ }
+
+ // 打印接收到的消息
+ printf("%s", buffer);
+ }
+
+ pthread_exit(NULL);
+}
+
+void handle_signal(int sig) {
+ printf("\nExiting...\n");
+ running = 0;
+ close(client_socket);
+ exit(EXIT_SUCCESS);
+}
+
+void login_register_menu() {
+ char buffer[BUFFER_SIZE];
+ int choice;
+ char username[BUFFER_SIZE];
+ char password[BUFFER_SIZE];
+
+ while (running) {
+ // 接收菜单
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+
+ // 发送选择
+ scanf("%d", &choice);
+ getchar(); // 消耗换行符
+ sprintf(buffer, "%d", choice);
+ if (send(client_socket, buffer, strlen(buffer), 0) == -1) {
+ perror("Send failed");
+ running = 0;
+ return;
+ }
+
+ // 处理登录
+ if (choice == 1) {
+ // 接收用户名提示
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+
+ // 发送用户名
+ fgets(username, BUFFER_SIZE - 1, stdin);
+ username[strcspn(username, "\n")] = 0; // 移除换行符
+ if (send(client_socket, username, strlen(username), 0) == -1) {
+ perror("Send failed");
+ running = 0;
+ return;
+ }
+
+ // 接收密码提示
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+
+ // 发送密码
+ fgets(password, BUFFER_SIZE - 1, stdin);
+ password[strcspn(password, "\n")] = 0; // 移除换行符
+ if (send(client_socket, password, strlen(password), 0) == -1) {
+ perror("Send failed");
+ running = 0;
+ return;
+ }
+
+ // 接收登录结果
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+
+ // 检查是否登录成功
+ if (strstr(buffer, "Login successful") != NULL) {
+ // 接收帮助信息
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) > 0) {
+ printf("%s", buffer);
+ }
+ break;
+ }
+ }
+ // 处理注册
+ else if (choice == 2) {
+ // 接收用户名提示
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+
+ // 发送用户名
+ fgets(username, BUFFER_SIZE - 1, stdin);
+ username[strcspn(username, "\n")] = 0; // 移除换行符
+ if (send(client_socket, username, strlen(username), 0) == -1) {
+ perror("Send failed");
+ running = 0;
+ return;
+ }
+
+ // 接收密码提示
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+
+ // 发送密码
+ fgets(password, BUFFER_SIZE - 1, stdin);
+ password[strcspn(password, "\n")] = 0; // 移除换行符
+ if (send(client_socket, password, strlen(password), 0) == -1) {
+ perror("Send failed");
+ running = 0;
+ return;
+ }
+
+ // 接收注册结果
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+ }
+ else {
+ // 接收无效选择提示
+ memset(buffer, 0, BUFFER_SIZE);
+ if (recv(client_socket, buffer, BUFFER_SIZE - 1, 0) <= 0) {
+ printf("Server disconnected.\n");
+ running = 0;
+ return;
+ }
+ printf("%s", buffer);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Project/server b/Project/server
new file mode 100644
index 0000000..10e3d80
Binary files /dev/null and b/Project/server differ
diff --git a/Project/server.c b/Project/server.c
new file mode 100644
index 0000000..c3702f5
--- /dev/null
+++ b/Project/server.c
@@ -0,0 +1,471 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define MAX_CLIENTS 10
+#define BUFFER_SIZE 1024
+#define USERNAME_LENGTH 50
+#define PASSWORD_LENGTH 50
+#define FILENAME "./users.txt"
+
+typedef struct {
+ int socket;
+ char username[USERNAME_LENGTH];
+ pthread_t thread;
+ int active;
+} Client;
+
+Client clients[MAX_CLIENTS];
+pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
+int server_socket;
+
+// 函数声明
+void handle_signal(int sig);
+void *handle_client(void *arg);
+int find_client_index(int socket);
+int find_client_index_by_username(const char *username);
+void send_private_message(const char *sender, const char *recipient, const char *message);
+void list_users(int client_socket);
+int authenticate_user(const char *username, const char *password);
+int register_user(const char *username, const char *password);
+void save_user(const char *username, const char *password);
+
+int main() {
+ int client_socket;
+ struct sockaddr_in server_addr, client_addr;
+ socklen_t client_addr_len = sizeof(client_addr);
+
+ // 创建socket
+ server_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (server_socket == -1) {
+ perror("Socket creation failed");
+ exit(EXIT_FAILURE);
+ }
+
+ // 设置socket选项
+ int opt = 1;
+ if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
+ perror("Setsockopt failed");
+ exit(EXIT_FAILURE);
+ }
+
+ // 准备服务器地址
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = INADDR_ANY;
+ server_addr.sin_port = htons(8888);
+
+ // 绑定socket
+ if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
+ perror("Bind failed");
+ exit(EXIT_FAILURE);
+ }
+
+ // 监听连接
+ if (listen(server_socket, 5) == -1) {
+ perror("Listen failed");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Server started. Waiting for connections...\n");
+
+ // 初始化客户端数组
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ clients[i].socket = -1;
+ clients[i].active = 0;
+ }
+
+ // 设置信号处理
+ signal(SIGINT, handle_signal);
+
+ // 接受客户端连接
+ while (1) {
+ client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
+ if (client_socket == -1) {
+ perror("Accept failed");
+ continue;
+ }
+
+ // 查找空闲位置
+ int i;
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ if (clients[i].socket == -1) {
+ pthread_mutex_lock(&clients_mutex);
+ clients[i].socket = client_socket;
+ clients[i].active = 1;
+ pthread_mutex_unlock(&clients_mutex);
+
+ // 创建线程处理客户端
+ if (pthread_create(&clients[i].thread, NULL, handle_client, &clients[i]) != 0) {
+ perror("Thread creation failed");
+ pthread_mutex_lock(&clients_mutex);
+ clients[i].socket = -1;
+ clients[i].active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+ close(client_socket);
+ }
+ pthread_detach(clients[i].thread);
+ break;
+ }
+ }
+
+ if (i == MAX_CLIENTS) {
+ // 服务器已满
+ char response[] = "Server is full. Try again later.\n";
+ send(client_socket, response, strlen(response), 0);
+ close(client_socket);
+ }
+ }
+
+ // 关闭服务器socket
+ close(server_socket);
+ return 0;
+}
+
+void handle_signal(int sig) {
+ printf("\nShutting down server...\n");
+
+ // 关闭所有客户端socket
+ pthread_mutex_lock(&clients_mutex);
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ if (clients[i].socket != -1) {
+ close(clients[i].socket);
+ clients[i].socket = -1;
+ clients[i].active = 0;
+ }
+ }
+ pthread_mutex_unlock(&clients_mutex);
+
+ // 关闭服务器socket
+ close(server_socket);
+ exit(EXIT_SUCCESS);
+}
+
+void *handle_client(void *arg) {
+ Client *client = (Client *)arg;
+ char buffer[BUFFER_SIZE];
+ int bytes_received;
+
+ // 登录/注册流程
+ while (1) {
+ // 发送菜单
+ char menu[] = "1. Login\n2. Register\nEnter choice: ";
+ send(client->socket, menu, strlen(menu), 0);
+
+ // 接收选择
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client->socket, buffer, BUFFER_SIZE - 1, 0);
+ if (bytes_received <= 0) {
+ pthread_mutex_lock(&clients_mutex);
+ client->active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+ close(client->socket);
+ pthread_exit(NULL);
+ }
+
+ int choice = atoi(buffer);
+
+ // 处理登录
+ if (choice == 1) {
+ // 请求用户名
+ char username_prompt[] = "Username: ";
+ send(client->socket, username_prompt, strlen(username_prompt), 0);
+
+ // 接收用户名
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client->socket, buffer, BUFFER_SIZE - 1, 0);
+ if (bytes_received <= 0) {
+ pthread_mutex_lock(&clients_mutex);
+ client->active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+ close(client->socket);
+ pthread_exit(NULL);
+ }
+ char username[USERNAME_LENGTH];
+ strncpy(username, buffer, USERNAME_LENGTH - 1);
+
+ // 请求密码
+ char password_prompt[] = "Password: ";
+ send(client->socket, password_prompt, strlen(password_prompt), 0);
+
+ // 接收密码
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client->socket, buffer, BUFFER_SIZE - 1, 0);
+ if (bytes_received <= 0) {
+ pthread_mutex_lock(&clients_mutex);
+ client->active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+ close(client->socket);
+ pthread_exit(NULL);
+ }
+ char password[PASSWORD_LENGTH];
+ strncpy(password, buffer, PASSWORD_LENGTH - 1);
+
+ // 验证用户
+ if (authenticate_user(username, password)) {
+ // 检查用户名是否已被使用
+ int username_in_use = 0;
+ pthread_mutex_lock(&clients_mutex);
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ if (i != find_client_index(client->socket) && clients[i].active &&
+ strcmp(clients[i].username, username) == 0) {
+ username_in_use = 1;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&clients_mutex);
+
+ if (username_in_use) {
+ char response[] = "Username already in use. Please try again.\n";
+ send(client->socket, response, strlen(response), 0);
+ } else {
+ // 登录成功
+ strcpy(client->username, username);
+ char success[] = "Login successful. Welcome to the chat!\n";
+ send(client->socket, success, strlen(success), 0);
+
+ // 通知用户可用命令
+ char help[] = "Available commands:\n/private - Send private message\n/list - List online users\n/quit - Exit chat\n";
+ send(client->socket, help, strlen(help), 0);
+
+ break;
+ }
+ } else {
+ char response[] = "Authentication failed. Please try again.\n";
+ send(client->socket, response, strlen(response), 0);
+ }
+ }
+ // 处理注册
+ else if (choice == 2) {
+ // 请求用户名
+ char username_prompt[] = "Enter username: ";
+ send(client->socket, username_prompt, strlen(username_prompt), 0);
+
+ // 接收用户名
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client->socket, buffer, BUFFER_SIZE - 1, 0);
+ if (bytes_received <= 0) {
+ pthread_mutex_lock(&clients_mutex);
+ client->active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+ close(client->socket);
+ pthread_exit(NULL);
+ }
+ char username[USERNAME_LENGTH];
+ strncpy(username, buffer, USERNAME_LENGTH - 1);
+
+ // 请求密码
+ char password_prompt[] = "Enter password: ";
+ send(client->socket, password_prompt, strlen(password_prompt), 0);
+
+ // 接收密码
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client->socket, buffer, BUFFER_SIZE - 1, 0);
+ if (bytes_received <= 0) {
+ pthread_mutex_lock(&clients_mutex);
+ client->active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+ close(client->socket);
+ pthread_exit(NULL);
+ }
+ char password[PASSWORD_LENGTH];
+ strncpy(password, buffer, PASSWORD_LENGTH - 1);
+
+ // 注册用户
+ if (register_user(username, password)) {
+ char success[] = "Registration successful. You can now login.\n";
+ send(client->socket, success, strlen(success), 0);
+ } else {
+ char response[] = "Registration failed. Username already exists.\n";
+ send(client->socket, response, strlen(response), 0);
+ }
+ }
+ else {
+ char response[] = "Invalid choice. Please try again.\n";
+ send(client->socket, response, strlen(response), 0);
+ }
+ }
+
+ // 聊天循环
+ while (1) {
+ memset(buffer, 0, BUFFER_SIZE);
+ bytes_received = recv(client->socket, buffer, BUFFER_SIZE - 1, 0);
+
+ if (bytes_received <= 0) {
+ // 客户端断开连接
+ break;
+ }
+
+ // 检查是否是退出命令
+ if (strncmp(buffer, "/quit", 5) == 0) {
+ break;
+ }
+
+ // 检查是否是列出用户命令
+ if (strncmp(buffer, "/list", 5) == 0) {
+ list_users(client->socket);
+ continue;
+ }
+
+ // 检查是否是私聊命令
+ if (strncmp(buffer, "/private", 7) == 0) {
+ char recipient[USERNAME_LENGTH];
+ char message[BUFFER_SIZE - USERNAME_LENGTH - 8];
+
+ // 解析命令
+ sscanf(buffer, "/private %s %[^\n]", recipient, message);
+
+ // 发送私聊消息
+ send_private_message(client->username, recipient, message);
+ continue;
+ }
+
+ // 发送帮助信息
+ char help[] = "Invalid command. Available commands:\n/private - Send private message\n/list - List online users\n/quit - Exit chat\n";
+ send(client->socket, help, strlen(help), 0);
+ }
+
+ // 客户端断开连接
+ char leave_message[BUFFER_SIZE];
+ snprintf(leave_message, BUFFER_SIZE, "%s has left the chat.\n", client->username);
+ pthread_mutex_lock(&clients_mutex);
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ if (i != find_client_index(client->socket) && clients[i].active) {
+ send(clients[i].socket, leave_message, strlen(leave_message), 0);
+ }
+ }
+ pthread_mutex_unlock(&clients_mutex);
+
+ // 关闭客户端socket
+ pthread_mutex_lock(&clients_mutex);
+ close(client->socket);
+ client->socket = -1;
+ client->active = 0;
+ pthread_mutex_unlock(&clients_mutex);
+
+ pthread_exit(NULL);
+}
+
+int find_client_index(int socket) {
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ if (clients[i].socket == socket) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int find_client_index_by_username(const char *username) {
+ pthread_mutex_lock(&clients_mutex);
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ if (clients[i].active && strcmp(clients[i].username, username) == 0) {
+ pthread_mutex_unlock(&clients_mutex);
+ return i;
+ }
+ }
+ pthread_mutex_unlock(&clients_mutex);
+ return -1;
+}
+
+void send_private_message(const char *sender, const char *recipient, const char *message) {
+ int recipient_index = find_client_index_by_username(recipient);
+
+ if (recipient_index == -1) {
+ char error[BUFFER_SIZE];
+ snprintf(error, BUFFER_SIZE, "Error: User '%s' not found or offline.\n", recipient);
+
+ int sender_index = find_client_index_by_username(sender);
+ if (sender_index != -1) {
+ send(clients[sender_index].socket, error, strlen(error), 0);
+ }
+ return;
+ }
+
+ // 发送消息给接收者
+ char private_message[BUFFER_SIZE];
+ snprintf(private_message, BUFFER_SIZE, "[Private from %s]: %s\n", sender, message);
+ send(clients[recipient_index].socket, private_message, strlen(private_message), 0);
+
+ // 发送确认给发送者
+ char confirmation[BUFFER_SIZE];
+ snprintf(confirmation, BUFFER_SIZE, "[Private to %s]: %s\n", recipient, message);
+ int sender_index = find_client_index_by_username(sender);
+ if (sender_index != -1) {
+ send(clients[sender_index].socket, confirmation, strlen(confirmation), 0);
+ }
+}
+
+void list_users(int client_socket) {
+ char response[BUFFER_SIZE] = "Online users:\n";
+
+ pthread_mutex_lock(&clients_mutex);
+ for (int i = 0; i < MAX_CLIENTS; i++) {
+ if (clients[i].active) {
+ strncat(response, clients[i].username, USERNAME_LENGTH - strlen(response) - 2);
+ strcat(response, "\n");
+ }
+ }
+ pthread_mutex_unlock(&clients_mutex);
+
+ send(client_socket, response, strlen(response), 0);
+}
+
+int authenticate_user(const char *username, const char *password) {
+ FILE *file = fopen(FILENAME, "r");
+ if (file == NULL) {
+ return 0;
+ }
+
+ char stored_username[USERNAME_LENGTH];
+ char stored_password[PASSWORD_LENGTH];
+ int found = 0;
+
+ while (fscanf(file, "%s %s", stored_username, stored_password) != EOF) {
+ if (strcmp(username, stored_username) == 0 && strcmp(password, stored_password) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ fclose(file);
+ return found;
+}
+
+int register_user(const char *username, const char *password) {
+ FILE *file = fopen(FILENAME, "r");
+ if (file == NULL) {
+ file = fopen(FILENAME, "w");
+ if (file == NULL) {
+ return 0;
+ }
+ fclose(file);
+ file = fopen(FILENAME, "r");
+ }
+
+ char stored_username[USERNAME_LENGTH];
+ while (fscanf(file, "%s", stored_username) != EOF) {
+ if (strcmp(username, stored_username) == 0) {
+ fclose(file);
+ return 0; // 用户名已存在
+ }
+ // 跳过密码
+ fscanf(file, "%*s");
+ }
+ fclose(file);
+
+ // 添加新用户
+ save_user(username, password);
+ return 1;
+}
+
+void save_user(const char *username, const char *password) {
+ FILE *file = fopen(FILENAME, "a");
+ if (file != NULL) {
+ fprintf(file, "%s %s\n", username, password);
+ fclose(file);
+ }
+}
\ No newline at end of file
diff --git a/Project/test/Client.c b/Project/test/Client.c
new file mode 100644
index 0000000..b93060c
--- /dev/null
+++ b/Project/test/Client.c
@@ -0,0 +1,422 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define MAX_BUFFER 1024
+#define PORT 8888
+#define SERVER_IP "127.0.0.1"
+#define MAX_FRIENDS 50
+
+// 好友结构体
+typedef struct {
+ char username[50];
+ int index;
+} Friend;
+
+// 全局变量
+int client_socket;
+int current_user_index = -1;
+char current_username[50];
+pthread_t receive_thread;
+Friend friends[MAX_FRIENDS];
+int friend_count = 0;
+
+// 函数声明
+void connect_to_server();
+void* receive_messages(void* arg);
+void show_login_menu();
+void show_main_menu();
+void login();
+void register_user();
+void add_friend();
+void remove_friend();
+void chat_with_friend();
+void logout();
+void get_friends_list();
+void display_friends_list();
+
+int main() {
+ connect_to_server();
+ show_login_menu();
+ return 0;
+}
+
+void connect_to_server() {
+ struct sockaddr_in server_addr;
+
+ // 创建socket
+ client_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (client_socket < 0) {
+ perror("创建Socket失败");
+ exit(EXIT_FAILURE);
+ }
+
+ // 设置服务器地址
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(PORT);
+ server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
+
+ // 连接服务器
+ if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
+ perror("连接服务器失败");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("成功连接到服务器!\n");
+ // 不要在这里启动接收线程
+}
+
+void* receive_messages(void* arg) {
+ char buffer[MAX_BUFFER];
+ while (1) {
+ memset(buffer, 0, MAX_BUFFER);
+ if (recv(client_socket, buffer, MAX_BUFFER, 0) <= 0) {
+ printf("\n连接已断开\n");
+ current_user_index = -1;
+ close(client_socket);
+ connect_to_server();
+ return NULL;
+ }
+
+ // 处理PING消息
+ if (strcmp(buffer, "PING") == 0) {
+ continue;
+ }
+
+ // 处理好友列表消息
+ if (strncmp(buffer, "FRIENDLIST", 10) == 0) {
+ friend_count = 0; // 重置好友计数
+ char* token = strtok(buffer + 11, " ");
+ while (token != NULL && friend_count < MAX_FRIENDS) {
+ char* comma = strchr(token, ',');
+ if (comma != NULL) {
+ *comma = '\0';
+ strncpy(friends[friend_count].username, token, sizeof(friends[friend_count].username)-1);
+ friends[friend_count].username[sizeof(friends[friend_count].username)-1] = '\0';
+ friends[friend_count].index = atoi(comma + 1);
+ friend_count++;
+ }
+ token = strtok(NULL, " ");
+ }
+ printf("\n好友列表已更新\n");
+ continue;
+ }
+
+ // 处理好友操作响应
+ if (strncmp(buffer, "FRIEND_ADD_SUCCESS", 17) == 0 ||
+ strncmp(buffer, "FRIEND_REMOVE_SUCCESS", 20) == 0) {
+ printf("\n%s\n", buffer);
+ get_friends_list();
+ continue;
+ }
+
+ // 处理聊天消息
+ if (strncmp(buffer, "CHAT", 4) == 0) {
+ printf("\n%s\n", buffer + 5);
+ }
+ // 处理系统消息
+ else if (strncmp(buffer, "系统消息", 8) == 0 ||
+ strncmp(buffer, "FRIEND_", 7) == 0) {
+ printf("\n%s\n", buffer);
+ }
+ // 处理其他消息
+ else {
+ printf("\n%s\n", buffer);
+ }
+
+ if (current_user_index != -1) {
+ printf("> ");
+ fflush(stdout);
+ }
+ }
+ return NULL;
+}
+
+void show_login_menu() {
+ int choice;
+ while (1) {
+ printf("\n=== 登录菜单 ===\n");
+ printf("1. 登录\n");
+ printf("2. 注册\n");
+ printf("3. 退出\n");
+ printf("请选择: ");
+ scanf("%d", &choice);
+ getchar(); // 清除输入缓冲
+
+ switch (choice) {
+ case 1:
+ login();
+ break;
+ case 2:
+ register_user();
+ break;
+ case 3:
+ logout(); // 确保在退出前发送登出消息
+ close(client_socket);
+ exit(EXIT_SUCCESS);
+ default:
+ printf("无效选择\n");
+ }
+ }
+}
+
+void show_main_menu() {
+ int choice;
+ while (current_user_index != -1) { // 只在用户已登录时显示菜单
+ printf("\n=== 主菜单 ===\n");
+ printf("1. 添加好友\n");
+ printf("2. 删除好友\n");
+ printf("3. 与好友聊天\n");
+ printf("4. 查看好友列表\n");
+ printf("5. 退出登录\n");
+ printf("6. 退出程序\n");
+ printf("请选择: ");
+
+ if (scanf("%d", &choice) != 1) {
+ // 清除输入缓冲
+ int c;
+ while ((c = getchar()) != '\n' && c != EOF);
+ printf("无效输入,请重新选择\n");
+ continue;
+ }
+ getchar(); // 清除输入缓冲
+
+ switch (choice) {
+ case 1:
+ add_friend();
+ break;
+ case 2:
+ remove_friend();
+ break;
+ case 3:
+ chat_with_friend();
+ break;
+ case 4:
+ get_friends_list();
+ display_friends_list();
+ break;
+ case 5:
+ logout();
+ return;
+ case 6:
+ logout();
+ close(client_socket);
+ exit(EXIT_SUCCESS);
+ default:
+ printf("无效选择\n");
+ }
+ }
+}
+
+void login() {
+ char username[50], password[50];
+ char buffer[MAX_BUFFER];
+ char response[MAX_BUFFER];
+
+ printf("用户名: ");
+ scanf("%s", username);
+ printf("密码: ");
+ scanf("%s", password);
+ getchar(); // 清除输入缓冲
+
+ snprintf(buffer, MAX_BUFFER, "LOGIN %s %s", username, password);
+ send(client_socket, buffer, MAX_BUFFER, 0);
+
+ // 等待服务器响应
+ memset(response, 0, MAX_BUFFER);
+ if (recv(client_socket, response, MAX_BUFFER, 0) <= 0) {
+ printf("登录失败:连接已断开\n");
+ return;
+ }
+
+ if (strncmp(response, "SUCCESS", 7) == 0) {
+ sscanf(response, "SUCCESS %d", ¤t_user_index);
+ strncpy(current_username, username, sizeof(current_username) - 1);
+ current_username[sizeof(current_username) - 1] = '\0';
+ printf("登录成功!\n");
+ // 登录成功后再启动接收线程
+ if (pthread_create(&receive_thread, NULL, receive_messages, NULL) != 0) {
+ perror("创建线程失败");
+ exit(EXIT_FAILURE);
+ }
+ get_friends_list();
+ show_main_menu();
+ } else {
+ printf("登录失败: %s\n", response + 5);
+ }
+}
+
+void register_user() {
+ char username[50], password[50];
+ char buffer[MAX_BUFFER];
+
+ printf("用户名: ");
+ scanf("%s", username);
+ printf("密码: ");
+ scanf("%s", password);
+
+ snprintf(buffer, MAX_BUFFER, "REGISTER %s %s", username, password);
+ send(client_socket, buffer, MAX_BUFFER, 0);
+
+ // 等待服务器响应
+ memset(buffer, 0, MAX_BUFFER);
+ recv(client_socket, buffer, MAX_BUFFER, 0);
+
+ if (strcmp(buffer, "SUCCESS") == 0) {
+ printf("注册成功!\n");
+ } else {
+ printf("注册失败: %s\n", buffer + 5);
+ }
+}
+
+void get_friends_list() {
+ char buffer[MAX_BUFFER];
+ snprintf(buffer, MAX_BUFFER, "GETFRIENDS %d", current_user_index);
+ send(client_socket, buffer, MAX_BUFFER, 0);
+ // 等待接收线程处理好友列表
+ usleep(100000); // 等待100ms
+}
+
+void display_friends_list() {
+ printf("\n=== 好友列表 ===\n");
+ if (friend_count == 0) {
+ printf("暂无好友\n");
+ } else {
+ for (int i = 0; i < friend_count; i++) {
+ printf("%d. %s\n", i + 1, friends[i].username);
+ }
+ }
+ printf("----------------\n");
+}
+
+void chat_with_friend() {
+ char buffer[MAX_BUFFER];
+ char message[MAX_BUFFER];
+ int choice;
+
+ get_friends_list();
+ if (friend_count == 0) {
+ printf("您还没有好友,请先添加好友!\n");
+ return;
+ }
+
+ display_friends_list();
+ printf("请选择要聊天的好友编号: ");
+ scanf("%d", &choice);
+ getchar(); // 清除输入缓冲
+
+ if (choice < 1 || choice > friend_count) {
+ printf("无效的选择!\n");
+ return;
+ }
+
+ int friend_index = friends[choice - 1].index;
+ printf("\n开始与 %s 聊天(输入'exit'退出):\n", friends[choice - 1].username);
+ printf("> ");
+ fflush(stdout);
+
+ while (1) {
+ fgets(message, sizeof(message), stdin);
+ message[strcspn(message, "\n")] = 0; // 移除换行符
+ // 限制 message 长度
+ message[sizeof(message)-1] = '\0';
+ if (strcmp(message, "exit") == 0) {
+ break;
+ }
+ int n = snprintf(buffer, MAX_BUFFER, "CHAT %d %d %s", current_user_index, friend_index, message);
+ if (n < 0 || n >= MAX_BUFFER) {
+ strcpy(&buffer[MAX_BUFFER-5], "...");
+ }
+ send(client_socket, buffer, MAX_BUFFER, 0);
+ printf("> ");
+ fflush(stdout);
+ }
+}
+
+void add_friend() {
+ char friend_name[50];
+ char buffer[MAX_BUFFER];
+
+ printf("请输入要添加的好友用户名: ");
+ if (scanf("%49s", friend_name) != 1) {
+ getchar();
+ printf("输入无效\n");
+ return;
+ }
+ getchar();
+
+ snprintf(buffer, MAX_BUFFER, "ADDFRIEND %d %s", current_user_index, friend_name);
+
+ // 设置发送超时
+ struct timeval tv;
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof tv);
+
+ if (send(client_socket, buffer, MAX_BUFFER, 0) <= 0) {
+ printf("发送请求失败\n");
+ return;
+ }
+
+ printf("添加好友请求已发送,等待服务器响应...\n");
+}
+
+void remove_friend() {
+ char buffer[MAX_BUFFER];
+
+ get_friends_list();
+ usleep(100000); // 等待好友列表更新
+
+ if (friend_count == 0) {
+ printf("您还没有好友!\n");
+ return;
+ }
+
+ display_friends_list();
+ printf("请输入要删除的好友编号: ");
+ int choice;
+ if (scanf("%d", &choice) != 1) {
+ getchar();
+ printf("输入无效!\n");
+ return;
+ }
+ getchar();
+
+ if (choice < 1 || choice > friend_count) {
+ printf("无效的选择!\n");
+ return;
+ }
+
+ // 设置发送超时
+ struct timeval tv;
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof tv);
+
+ snprintf(buffer, MAX_BUFFER, "REMOVEFRIEND %d %s",
+ current_user_index,
+ friends[choice - 1].username);
+
+ if (send(client_socket, buffer, MAX_BUFFER, 0) <= 0) {
+ printf("发送请求失败\n");
+ return;
+ }
+
+ printf("删除好友请求已发送,等待服务器响应...\n");
+}
+
+void logout() {
+ if (current_user_index != -1) {
+ char buffer[MAX_BUFFER];
+ snprintf(buffer, MAX_BUFFER, "LOGOUT");
+ send(client_socket, buffer, MAX_BUFFER, 0);
+ current_user_index = -1;
+ printf("已退出登录\n");
+ }
+}
\ No newline at end of file
diff --git a/Project/test/Server.c b/Project/test/Server.c
new file mode 100644
index 0000000..b764959
--- /dev/null
+++ b/Project/test/Server.c
@@ -0,0 +1,517 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define MAX_BUFFER 1024
+#define MAX_USERS 100
+#define MAX_FRIENDS 50
+#define PORT 8888
+
+// 用户结构体
+typedef struct {
+ char username[50];
+ char password[50];
+ int friends[MAX_FRIENDS];
+ int friend_count;
+ int online;
+ int socket; // 添加socket字段
+} User;
+
+// 全局变量
+User users[MAX_USERS];
+int user_count = 0;
+pthread_mutex_t users_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// 函数声明
+void load_users();
+void save_users();
+int find_user(const char* username);
+void* handle_client(void* arg);
+void process_login(int client_socket, char* buffer);
+void process_register(int client_socket, char* buffer);
+void process_add_friend(int client_socket, char* buffer);
+void process_remove_friend(int client_socket, char* buffer);
+void process_chat(int client_socket, char* buffer);
+void display_online_users(); // 新增函数声明
+void process_get_friends(int client_socket, char* buffer);
+
+int main() {
+ int server_socket, client_socket;
+ struct sockaddr_in server_addr, client_addr;
+ socklen_t client_len = sizeof(client_addr);
+ pthread_t thread_id;
+
+ // 加载用户数据
+ load_users();
+
+ // 创建socket
+ server_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (server_socket < 0) {
+ perror("创建Socket失败");
+ exit(EXIT_FAILURE);
+ }
+
+ // 设置服务器地址
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = INADDR_ANY;
+ server_addr.sin_port = htons(PORT);
+
+ // 绑定socket
+ if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
+ perror("绑定失败");
+ exit(EXIT_FAILURE);
+ }
+
+ // 监听连接
+ if (listen(server_socket, 5) < 0) {
+ perror("监听失败");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("服务器已启动,监听端口 %d\n", PORT);
+
+ // 接受客户端连接
+ while (1) {
+ client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_len);
+ if (client_socket < 0) {
+ perror("接受连接失败");
+ continue;
+ }
+
+ printf("新客户端连接:%s:%d\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
+
+ // 为每个客户端创建新线程
+ if (pthread_create(&thread_id, NULL, handle_client, (void*)&client_socket) != 0) {
+ perror("创建线程失败");
+ close(client_socket);
+ }
+ }
+
+ close(server_socket);
+ return 0;
+}
+
+void load_users() {
+ FILE* file = fopen("Users.txt", "r");
+ if (file == NULL) {
+ printf("未找到用户文件,将创建新文件。\n");
+ return;
+ }
+
+ while (fscanf(file, "%s %s %d", users[user_count].username,
+ users[user_count].password, &users[user_count].friend_count) == 3) {
+ for (int i = 0; i < users[user_count].friend_count; i++) {
+ fscanf(file, "%d", &users[user_count].friends[i]);
+ }
+ users[user_count].online = 0;
+ users[user_count].socket = -1;
+ user_count++;
+ }
+
+ fclose(file);
+}
+
+void save_users() {
+ FILE* file = fopen("Users.txt", "w");
+ if (file == NULL) {
+ perror("无法打开用户文件");
+ return;
+ }
+
+ for (int i = 0; i < user_count; i++) {
+ fprintf(file, "%s %s %d", users[i].username,
+ users[i].password, users[i].friend_count);
+ for (int j = 0; j < users[i].friend_count; j++) {
+ fprintf(file, " %d", users[i].friends[j]);
+ }
+ fprintf(file, "\n");
+ }
+
+ fclose(file);
+}
+
+int find_user(const char* username) {
+ for (int i = 0; i < user_count; i++) {
+ if (strcmp(users[i].username, username) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void* handle_client(void* arg) {
+ int client_socket = *((int*)arg);
+ char buffer[MAX_BUFFER];
+ int user_index = -1;
+
+ // 设置socket选项,启用保活机制
+ int keepalive = 1;
+ int keepidle = 5; // 5秒没有数据交互就开始探测
+ int keepinterval = 2; // 探测间隔2秒
+ int keepcount = 3; // 探测3次无响应就断开
+
+ setsockopt(client_socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive));
+ setsockopt(client_socket, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
+ setsockopt(client_socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval));
+ setsockopt(client_socket, IPPROTO_TCP, TCP_KEEPCNT, &keepcount, sizeof(keepcount));
+
+ while (1) {
+ memset(buffer, 0, MAX_BUFFER);
+ int bytes_received = recv(client_socket, buffer, MAX_BUFFER, 0);
+
+ // 检查连接状态
+ if (bytes_received <= 0) {
+ pthread_mutex_lock(&users_mutex);
+ // 查找并更新断开连接的用户状态
+ for (int i = 0; i < user_count; i++) {
+ if (users[i].socket == client_socket) {
+ user_index = i;
+ users[i].online = 0;
+ users[i].socket = -1;
+ printf("\n用户 %s 断开连接\n", users[i].username);
+
+ // 通知所有在线好友
+ for (int j = 0; j < users[i].friend_count; j++) {
+ int friend_index = users[i].friends[j];
+ if (users[friend_index].online && users[friend_index].socket != -1) {
+ char notify[MAX_BUFFER];
+ sprintf(notify, "系统消息: 您的好友 %s 已离线", users[i].username);
+ send(users[friend_index].socket, notify, MAX_BUFFER, 0);
+ }
+ }
+ break;
+ }
+ }
+ save_users();
+ display_online_users();
+ pthread_mutex_unlock(&users_mutex);
+ break;
+ }
+
+ char command[20];
+ sscanf(buffer, "%s", command);
+
+ if (strcmp(command, "LOGIN") == 0) {
+ process_login(client_socket, buffer);
+ // 更新user_index
+ for (int i = 0; i < user_count; i++) {
+ if (users[i].socket == client_socket) {
+ user_index = i;
+ break;
+ }
+ }
+ }
+ else if (strcmp(command, "REGISTER") == 0) {
+ process_register(client_socket, buffer);
+ }
+ else if (strcmp(command, "ADDFRIEND") == 0) {
+ process_add_friend(client_socket, buffer);
+ }
+ else if (strcmp(command, "REMOVEFRIEND") == 0) {
+ process_remove_friend(client_socket, buffer);
+ }
+ else if (strcmp(command, "CHAT") == 0) {
+ process_chat(client_socket, buffer);
+ }
+ else if (strcmp(command, "LOGOUT") == 0) {
+ pthread_mutex_lock(&users_mutex);
+ // 查找当前用户
+ for (int i = 0; i < user_count; i++) {
+ if (users[i].socket == client_socket) {
+ user_index = i;
+ break;
+ }
+ }
+
+ if (user_index != -1) {
+ users[user_index].online = 0;
+ users[user_index].socket = -1;
+ // 通知所有在线好友
+ for (int i = 0; i < users[user_index].friend_count; i++) {
+ int friend_index = users[user_index].friends[i];
+ if (users[friend_index].online && users[friend_index].socket != -1) {
+ char notify[MAX_BUFFER];
+ sprintf(notify, "系统消息: 您的好友 %s 已离线", users[user_index].username);
+ send(users[friend_index].socket, notify, MAX_BUFFER, 0);
+ }
+ }
+ save_users();
+ printf("\n用户 %s 退出登录\n", users[user_index].username);
+ display_online_users();
+ }
+ pthread_mutex_unlock(&users_mutex);
+ break;
+ }
+ else if (strcmp(command, "GETFRIENDS") == 0) {
+ process_get_friends(client_socket, buffer);
+ }
+ }
+
+ // 确保在断开连接时清理用户状态
+ if (user_index != -1) {
+ pthread_mutex_lock(&users_mutex);
+ users[user_index].online = 0;
+ users[user_index].socket = -1;
+ save_users();
+ display_online_users();
+ pthread_mutex_unlock(&users_mutex);
+ }
+
+ close(client_socket);
+ return NULL;
+}
+
+void process_login(int client_socket, char* buffer) {
+ char username[50], password[50];
+ sscanf(buffer, "LOGIN %s %s", username, password);
+
+ pthread_mutex_lock(&users_mutex);
+ int user_index = find_user(username);
+
+ if (user_index == -1) {
+ send(client_socket, "FAIL 用户不存在", MAX_BUFFER, 0);
+ }
+ else if (strcmp(users[user_index].password, password) != 0) {
+ send(client_socket, "FAIL 密码错误", MAX_BUFFER, 0);
+ }
+ else {
+ // 如果用户已经在线,先将其标记为离线
+ if (users[user_index].online) {
+ users[user_index].online = 0;
+ users[user_index].socket = -1;
+ }
+
+ // 更新用户状态
+ users[user_index].online = 1;
+ users[user_index].socket = client_socket;
+ save_users();
+
+ char response[MAX_BUFFER];
+ snprintf(response, MAX_BUFFER, "SUCCESS %d", user_index);
+ send(client_socket, response, MAX_BUFFER, 0);
+ printf("\n用户 %s 登录成功\n", username);
+
+ // 通知所有在线好友
+ for (int i = 0; i < users[user_index].friend_count; i++) {
+ int friend_index = users[user_index].friends[i];
+ if (users[friend_index].online && users[friend_index].socket != -1) {
+ char notify[MAX_BUFFER];
+ snprintf(notify, MAX_BUFFER, "系统消息: 您的好友 %s 已上线", username);
+ send(users[friend_index].socket, notify, MAX_BUFFER, 0);
+ }
+ }
+ display_online_users();
+ }
+ pthread_mutex_unlock(&users_mutex);
+}
+
+void process_register(int client_socket, char* buffer) {
+ char username[50], password[50];
+ sscanf(buffer, "REGISTER %s %s", username, password);
+
+ pthread_mutex_lock(&users_mutex);
+ if (find_user(username) != -1) {
+ send(client_socket, "FAIL 用户名已存在", MAX_BUFFER, 0);
+ }
+ else if (user_count >= MAX_USERS) {
+ send(client_socket, "FAIL 用户数量已达上限", MAX_BUFFER, 0);
+ }
+ else {
+ strcpy(users[user_count].username, username);
+ strcpy(users[user_count].password, password);
+ users[user_count].friend_count = 0;
+ users[user_count].online = 0;
+ users[user_count].socket = -1;
+ user_count++;
+ save_users();
+ send(client_socket, "SUCCESS", MAX_BUFFER, 0);
+ }
+ pthread_mutex_unlock(&users_mutex);
+}
+
+void process_add_friend(int client_socket, char* buffer) {
+ int user_index;
+ char friend_name[50];
+ sscanf(buffer, "ADDFRIEND %d %s", &user_index, friend_name);
+
+ pthread_mutex_lock(&users_mutex);
+ int friend_index = find_user(friend_name);
+
+ if (friend_index == -1) {
+ send(client_socket, "FAIL 好友不存在", MAX_BUFFER, 0);
+ }
+ else if (user_index == friend_index) {
+ send(client_socket, "FAIL 不能添加自己为好友", MAX_BUFFER, 0);
+ }
+ else {
+ // 检查是否已经是好友
+ for (int i = 0; i < users[user_index].friend_count; i++) {
+ if (users[user_index].friends[i] == friend_index) {
+ send(client_socket, "FAIL 已经是好友关系", MAX_BUFFER, 0);
+ pthread_mutex_unlock(&users_mutex);
+ return;
+ }
+ }
+
+ // 添加好友
+ users[user_index].friends[users[user_index].friend_count++] = friend_index;
+ users[friend_index].friends[users[friend_index].friend_count++] = user_index;
+ save_users();
+ send(client_socket, "SUCCESS", MAX_BUFFER, 0);
+
+ // 通知被添加的用户
+ if (users[friend_index].online && users[friend_index].socket != -1) {
+ char notify[MAX_BUFFER];
+ snprintf(notify, MAX_BUFFER, "系统消息: %s 添加您为好友", users[user_index].username);
+ send(users[friend_index].socket, notify, MAX_BUFFER, 0);
+ }
+ }
+ pthread_mutex_unlock(&users_mutex);
+}
+
+void process_remove_friend(int client_socket, char* buffer) {
+ int user_index;
+ char friend_name[50];
+ sscanf(buffer, "REMOVEFRIEND %d %s", &user_index, friend_name);
+
+ pthread_mutex_lock(&users_mutex);
+ int friend_index = find_user(friend_name);
+
+ if (friend_index == -1) {
+ send(client_socket, "FAIL 好友不存在", MAX_BUFFER, 0);
+ pthread_mutex_unlock(&users_mutex);
+ return;
+ }
+
+ int found = 0;
+ // 从用户的好友列表中移除
+ for (int i = 0; i < users[user_index].friend_count; i++) {
+ if (users[user_index].friends[i] == friend_index) {
+ for (int j = i; j < users[user_index].friend_count - 1; j++) {
+ users[user_index].friends[j] = users[user_index].friends[j + 1];
+ }
+ users[user_index].friend_count--;
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ // 从好友的好友列表中移除
+ for (int i = 0; i < users[friend_index].friend_count; i++) {
+ if (users[friend_index].friends[i] == user_index) {
+ for (int j = i; j < users[friend_index].friend_count - 1; j++) {
+ users[friend_index].friends[j] = users[friend_index].friends[j + 1];
+ }
+ users[friend_index].friend_count--;
+ break;
+ }
+ }
+
+ save_users();
+
+ // 发送成功响应
+ send(client_socket, "FRIEND_REMOVE_SUCCESS", MAX_BUFFER, 0);
+
+ // 发送通知给被删除的好友
+ if (users[friend_index].online && users[friend_index].socket != -1) {
+ char notify[MAX_BUFFER];
+ snprintf(notify, MAX_BUFFER, "FRIEND_REMOVE %s 将您从好友列表中移除",
+ users[user_index].username);
+ send(users[friend_index].socket, notify, MAX_BUFFER, 0);
+ }
+ } else {
+ send(client_socket, "FAIL 不是好友关系", MAX_BUFFER, 0);
+ }
+
+ pthread_mutex_unlock(&users_mutex);
+}
+
+void process_chat(int client_socket, char* buffer) {
+ int user_index, friend_index;
+ char message[MAX_BUFFER];
+ sscanf(buffer, "CHAT %d %d %[^\n]", &user_index, &friend_index, message);
+ pthread_mutex_lock(&users_mutex);
+ // 验证是否是好友关系
+ int is_friend = 0;
+ for (int i = 0; i < users[user_index].friend_count; i++) {
+ if (users[user_index].friends[i] == friend_index) {
+ is_friend = 1;
+ break;
+ }
+ }
+
+ if (!is_friend) {
+ send(client_socket, "FAIL 不是好友关系", MAX_BUFFER, 0);
+ }
+ else {
+ char response[MAX_BUFFER];
+ // 限制 message 长度,防止溢出
+ char safe_message[MAX_BUFFER/2];
+ strncpy(safe_message, message, sizeof(safe_message) - 1);
+ safe_message[sizeof(safe_message) - 1] = '\0';
+ int n = snprintf(response, MAX_BUFFER, "CHAT %s: %s", users[user_index].username, safe_message);
+ if (n < 0 || n >= MAX_BUFFER) {
+ // 被截断,补上 ...
+ strcpy(&response[MAX_BUFFER-5], "...");
+ }
+ // 发送给发送者
+ send(client_socket, response, MAX_BUFFER, 0);
+ // 发送给接收者
+ if (users[friend_index].online && users[friend_index].socket != -1) {
+ send(users[friend_index].socket, response, MAX_BUFFER, 0);
+ } else {
+ // 好友不在线,给发送者提示
+ send(client_socket, "系统消息: 对方不在线,消息未送达", MAX_BUFFER, 0);
+ }
+ }
+ pthread_mutex_unlock(&users_mutex);
+}
+
+// 新增函数:显示在线用户
+void display_online_users() {
+ printf("\n当前在线用户:\n");
+ int online_count = 0;
+ for (int i = 0; i < user_count; i++) {
+ if (users[i].online) {
+ printf("%d. %s\n", ++online_count, users[i].username);
+ }
+ }
+ if (online_count == 0) {
+ printf("暂无在线用户\n");
+ }
+ printf("------------------------\n");
+}
+
+// 新增函数:处理获取好友列表请求
+void process_get_friends(int client_socket, char* buffer) {
+ int user_index;
+ sscanf(buffer, "GETFRIENDS %d", &user_index);
+
+ pthread_mutex_lock(&users_mutex);
+ char response[MAX_BUFFER] = "FRIENDLIST ";
+ char temp[64];
+
+ for (int i = 0; i < users[user_index].friend_count; i++) {
+ int friend_index = users[user_index].friends[i];
+ int n = snprintf(temp, sizeof(temp), "%s,%d ", users[friend_index].username, friend_index);
+ if (n < 0 || n >= sizeof(temp)) {
+ strcpy(&temp[sizeof(temp)-5], "...");
+ }
+ if (strlen(response) + strlen(temp) < MAX_BUFFER) {
+ strcat(response, temp);
+ } else {
+ strcat(response, "...");
+ break;
+ }
+ }
+ send(client_socket, response, MAX_BUFFER, 0);
+ pthread_mutex_unlock(&users_mutex);
+}
\ No newline at end of file
diff --git a/Project/test/client b/Project/test/client
new file mode 100644
index 0000000..1aa97e6
Binary files /dev/null and b/Project/test/client differ
diff --git a/Project/test/server b/Project/test/server
new file mode 100644
index 0000000..8c18d30
Binary files /dev/null and b/Project/test/server differ
diff --git a/Project/users.txt b/Project/users.txt
new file mode 100644
index 0000000..7edc84d
--- /dev/null
+++ b/Project/users.txt
@@ -0,0 +1 @@
+test password
diff --git a/Project/新建文件夹/Client_Cursor.c b/Project/新建文件夹/Client_Cursor.c
new file mode 100644
index 0000000..bcdd5a0
--- /dev/null
+++ b/Project/新建文件夹/Client_Cursor.c
@@ -0,0 +1,108 @@
+// client.c
+#include
+#include
+#include
+#include
+#include
+#include
+#include "protocol.h"
+
+#define SERVER_IP "127.0.0.1"
+#define PORT 8888
+
+int sockfd;
+char username[MAX_NAME_LEN];
+
+// 接收消息线程
+void *recv_thread(void *arg) {
+ Message msg;
+ while (1) {
+ int n = recv(sockfd, &msg, sizeof(msg), 0);
+ if (n <= 0) break;
+ if (msg.type == MSG_PRIVATE_CHAT) {
+ printf("\n[私聊]%s: %s\n", msg.from, msg.data);
+ printf(">> ");
+ fflush(stdout);
+ }
+ }
+ return NULL;
+}
+
+void menu() {
+ printf("1. 注册\n2. 登录\n选择: ");
+}
+
+void chat_menu() {
+ printf("1. 添加好友\n2. 私聊\n3. 退出\n选择: ");
+}
+
+int main() {
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ struct sockaddr_in servaddr = {0};
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(PORT);
+ inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr);
+ connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
+
+ int choice;
+ Message msg, reply;
+ while (1) {
+ menu();
+ scanf("%d", &choice);
+ getchar();
+ memset(&msg, 0, sizeof(msg));
+ if (choice == 1) {
+ msg.type = MSG_REGISTER;
+ printf("用户名: "); fgets(msg.from, MAX_NAME_LEN, stdin); msg.from[strcspn(msg.from, "\n")] = 0;
+ printf("密码: "); fgets(msg.data, MAX_MSG_LEN, stdin); msg.data[strcspn(msg.data, "\n")] = 0;
+ send(sockfd, &msg, sizeof(msg), 0);
+ recv(sockfd, &reply, sizeof(reply), 0);
+ if (reply.type == MSG_OK) printf("注册成功\n");
+ else printf("注册失败: %s\n", reply.data);
+ } else if (choice == 2) {
+ msg.type = MSG_LOGIN;
+ printf("用户名: "); fgets(msg.from, MAX_NAME_LEN, stdin); msg.from[strcspn(msg.from, "\n")] = 0;
+ printf("密码: "); fgets(msg.data, MAX_MSG_LEN, stdin); msg.data[strcspn(msg.data, "\n")] = 0;
+ send(sockfd, &msg, sizeof(msg), 0);
+ recv(sockfd, &reply, sizeof(reply), 0);
+ if (reply.type == MSG_OK) {
+ strcpy(username, msg.from);
+ printf("登录成功\n");
+ break;
+ } else {
+ printf("登录失败: %s\n", reply.data);
+ }
+ }
+ }
+
+ pthread_t tid;
+ pthread_create(&tid, NULL, recv_thread, NULL);
+
+ while (1) {
+ chat_menu();
+ scanf("%d", &choice);
+ getchar();
+ if (choice == 1) {
+ msg.type = MSG_ADD_FRIEND;
+ strcpy(msg.from, username);
+ printf("好友用户名: "); fgets(msg.to, MAX_NAME_LEN, stdin); msg.to[strcspn(msg.to, "\n")] = 0;
+ send(sockfd, &msg, sizeof(msg), 0);
+ recv(sockfd, &reply, sizeof(reply), 0);
+ if (reply.type == MSG_OK) printf("添加好友成功\n");
+ else printf("添加失败: %s\n", reply.data);
+ } else if (choice == 2) {
+ msg.type = MSG_PRIVATE_CHAT;
+ strcpy(msg.from, username);
+ printf("好友用户名: "); fgets(msg.to, MAX_NAME_LEN, stdin); msg.to[strcspn(msg.to, "\n")] = 0;
+ printf("消息内容: "); fgets(msg.data, MAX_MSG_LEN, stdin); msg.data[strcspn(msg.data, "\n")] = 0;
+ send(sockfd, &msg, sizeof(msg), 0);
+ recv(sockfd, &reply, sizeof(reply), 0);
+ if (reply.type == MSG_OK) printf("消息已发送\n");
+ else printf("发送失败: %s\n", reply.data);
+ } else if (choice == 3) {
+ break;
+ }
+ }
+ close(sockfd);
+ return 0;
+}
\ No newline at end of file
diff --git a/Project/新建文件夹/Server_Cursor.c b/Project/新建文件夹/Server_Cursor.c
new file mode 100644
index 0000000..9835825
--- /dev/null
+++ b/Project/新建文件夹/Server_Cursor.c
@@ -0,0 +1,138 @@
+// server.c
+#include
+#include
+#include
+#include
+#include
+#include
+#include "protocol.h"
+#include "user.h"
+
+#define PORT 8888
+#define MAX_USERS 100
+#define MAX_CLIENTS 100
+
+typedef struct {
+ int sockfd;
+ char username[MAX_NAME_LEN];
+} Client;
+
+User users[MAX_USERS];
+int user_count = 0;
+Client clients[MAX_CLIENTS];
+int client_count = 0;
+pthread_mutex_t user_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t client_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// 查找在线客户端
+int find_client(const char *username) {
+ for (int i = 0; i < client_count; i++) {
+ if (strcmp(clients[i].username, username) == 0)
+ return i;
+ }
+ return -1;
+}
+
+// 处理客户端请求
+void *client_handler(void *arg) {
+ int sockfd = *(int *)arg;
+ char curr_user[MAX_NAME_LEN] = "";
+ Message msg, reply;
+ while (1) {
+ int n = recv(sockfd, &msg, sizeof(msg), 0);
+ if (n <= 0) break;
+ memset(&reply, 0, sizeof(reply));
+ switch (msg.type) {
+ case MSG_REGISTER:
+ pthread_mutex_lock(&user_mutex);
+ if (add_user(users, &user_count, msg.from, msg.data)) {
+ save_users(users, user_count);
+ reply.type = MSG_OK;
+ } else {
+ reply.type = MSG_FAIL;
+ strcpy(reply.data, "用户名已存在");
+ }
+ pthread_mutex_unlock(&user_mutex);
+ send(sockfd, &reply, sizeof(reply), 0);
+ break;
+ case MSG_LOGIN:
+ pthread_mutex_lock(&user_mutex);
+ if (check_password(users, user_count, msg.from, msg.data)) {
+ strcpy(curr_user, msg.from);
+ pthread_mutex_lock(&client_mutex);
+ strcpy(clients[client_count].username, curr_user);
+ clients[client_count++].sockfd = sockfd;
+ pthread_mutex_unlock(&client_mutex);
+ reply.type = MSG_OK;
+ } else {
+ reply.type = MSG_FAIL;
+ strcpy(reply.data, "用户名或密码错误");
+ }
+ pthread_mutex_unlock(&user_mutex);
+ send(sockfd, &reply, sizeof(reply), 0);
+ break;
+ case MSG_ADD_FRIEND:
+ pthread_mutex_lock(&user_mutex);
+ if (add_friend(users, user_count, curr_user, msg.to)) {
+ save_users(users, user_count);
+ reply.type = MSG_OK;
+ } else {
+ reply.type = MSG_FAIL;
+ strcpy(reply.data, "添加好友失败");
+ }
+ pthread_mutex_unlock(&user_mutex);
+ send(sockfd, &reply, sizeof(reply), 0);
+ break;
+ case MSG_PRIVATE_CHAT:
+ pthread_mutex_lock(&client_mutex);
+ int idx = find_client(msg.to);
+ if (idx != -1) {
+ send(clients[idx].sockfd, &msg, sizeof(msg), 0);
+ reply.type = MSG_OK;
+ } else {
+ reply.type = MSG_FAIL;
+ strcpy(reply.data, "对方不在线");
+ }
+ pthread_mutex_unlock(&client_mutex);
+ send(sockfd, &reply, sizeof(reply), 0);
+ break;
+ default:
+ break;
+ }
+ }
+ // 客户端断开,移除
+ pthread_mutex_lock(&client_mutex);
+ for (int i = 0; i < client_count; i++) {
+ if (clients[i].sockfd == sockfd) {
+ clients[i] = clients[--client_count];
+ break;
+ }
+ }
+ pthread_mutex_unlock(&client_mutex);
+ close(sockfd);
+ return NULL;
+}
+
+int main() {
+ int listenfd = socket(AF_INET, SOCK_STREAM, 0);
+ struct sockaddr_in servaddr = {0};
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = INADDR_ANY;
+ servaddr.sin_port = htons(PORT);
+ bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
+ listen(listenfd, 5);
+
+ user_count = load_users(users, MAX_USERS);
+ printf("服务器启动,监听端口%d\n", PORT);
+
+ while (1) {
+ struct sockaddr_in cliaddr;
+ socklen_t len = sizeof(cliaddr);
+ int connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len);
+ pthread_t tid;
+ pthread_create(&tid, NULL, client_handler, &connfd);
+ pthread_detach(tid);
+ }
+ close(listenfd);
+ return 0;
+}
\ No newline at end of file
diff --git a/Project/新建文件夹/User.c b/Project/新建文件夹/User.c
new file mode 100644
index 0000000..2fc10bf
--- /dev/null
+++ b/Project/新建文件夹/User.c
@@ -0,0 +1,94 @@
+// user.c
+#include "user.h"
+#include
+#include
+
+#define USER_FILE "users.txt"
+#define MAX_LINE 256
+
+// 加载所有用户
+int load_users(User users[], int max_users) {
+ FILE *fp = fopen(USER_FILE, "r");
+ if (!fp) return 0;
+ int count = 0;
+ char line[MAX_LINE];
+ while (fgets(line, sizeof(line), fp) && count < max_users) {
+ User *u = &users[count];
+ char *p = strtok(line, " \n");
+ if (!p) continue;
+ strcpy(u->username, p);
+ p = strtok(NULL, " \n");
+ if (!p) continue;
+ strcpy(u->password, p);
+ u->friend_count = 0;
+ p = strtok(NULL, " \n");
+ if (p) {
+ char *f = strtok(p, ",");
+ while (f && u->friend_count < MAX_FRIENDS) {
+ strcpy(u->friends[u->friend_count++], f);
+ f = strtok(NULL, ",");
+ }
+ }
+ count++;
+ }
+ fclose(fp);
+ return count;
+}
+
+// 保存所有用户
+int save_users(User users[], int user_count) {
+ FILE *fp = fopen(USER_FILE, "w");
+ if (!fp) return -1;
+ for (int i = 0; i < user_count; i++) {
+ fprintf(fp, "%s %s", users[i].username, users[i].password);
+ for (int j = 0; j < users[i].friend_count; j++) {
+ fprintf(fp, "%c%s", j == 0 ? ' ' : ',', users[i].friends[j]);
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+ return 0;
+}
+
+// 查找用户
+int find_user(User users[], int user_count, const char *username) {
+ for (int i = 0; i < user_count; i++) {
+ if (strcmp(users[i].username, username) == 0)
+ return i;
+ }
+ return -1;
+}
+
+// 检查密码
+int check_password(User users[], int user_count, const char *username, const char *password) {
+ int idx = find_user(users, user_count, username);
+ if (idx == -1) return 0;
+ return strcmp(users[idx].password, password) == 0;
+}
+
+// 添加用户
+int add_user(User users[], int *user_count, const char *username, const char *password) {
+ if (find_user(users, *user_count, username) != -1) return 0;
+ User *u = &users[(*user_count)++];
+ strcpy(u->username, username);
+ strcpy(u->password, password);
+ u->friend_count = 0;
+ return 1;
+}
+
+// 添加好友
+int add_friend(User users[], int user_count, const char *username, const char *friendname) {
+ int idx = find_user(users, user_count, username);
+ int fidx = find_user(users, user_count, friendname);
+ if (idx == -1 || fidx == -1) return 0;
+ User *u = &users[idx];
+ for (int i = 0; i < u->friend_count; i++) {
+ if (strcmp(u->friends[i], friendname) == 0)
+ return 0; // 已是好友
+ }
+ if (u->friend_count < MAX_FRIENDS) {
+ strcpy(u->friends[u->friend_count++], friendname);
+ return 1;
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/Project/新建文件夹/User.h b/Project/新建文件夹/User.h
new file mode 100644
index 0000000..42e8aa1
--- /dev/null
+++ b/Project/新建文件夹/User.h
@@ -0,0 +1,21 @@
+// user.h
+#ifndef USER_H
+#define USER_H
+
+#define MAX_FRIENDS 10
+
+typedef struct {
+ char username[32];
+ char password[32];
+ char friends[MAX_FRIENDS][32];
+ int friend_count;
+} User;
+
+int load_users(User users[], int max_users);
+int save_users(User users[], int user_count);
+int find_user(User users[], int user_count, const char *username);
+int check_password(User users[], int user_count, const char *username, const char *password);
+int add_user(User users[], int *user_count, const char *username, const char *password);
+int add_friend(User users[], int user_count, const char *username, const char *friendname);
+
+#endif
\ No newline at end of file
diff --git a/Project/新建文件夹/protocol.h b/Project/新建文件夹/protocol.h
new file mode 100644
index 0000000..ef0ce70
--- /dev/null
+++ b/Project/新建文件夹/protocol.h
@@ -0,0 +1,22 @@
+// protocol.h
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+#define MSG_REGISTER 1
+#define MSG_LOGIN 2
+#define MSG_ADD_FRIEND 3
+#define MSG_PRIVATE_CHAT 4
+#define MSG_OK 100
+#define MSG_FAIL 101
+
+#define MAX_NAME_LEN 32
+#define MAX_MSG_LEN 256
+
+typedef struct {
+ int type; // 消息类型
+ char from[MAX_NAME_LEN];
+ char to[MAX_NAME_LEN];
+ char data[MAX_MSG_LEN];
+} Message;
+
+#endif
\ No newline at end of file
diff --git a/Project/新建文件夹/users.txt b/Project/新建文件夹/users.txt
new file mode 100644
index 0000000..7edc84d
--- /dev/null
+++ b/Project/新建文件夹/users.txt
@@ -0,0 +1 @@
+test password