#include #include #include #include #include #include #include #include #define MAX_BUFFER 1024 #define PORT 8888 #define SERVER_IP "8.137.76.175" #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"); } }