单线程Client-Server系统:客户端选择与服务器联动实现问询
问题解决:客户端-服务器模式下通过Switch Case实现操作选择同步
你的核心问题是客户端选择操作后未先告知服务器,且Switch Case存在逻辑贯穿错误,导致服务器无法正确识别客户端的操作意图。以下是具体修正方案:
关键修改点
1. 客户端先发送操作选择,再执行对应逻辑
无论用户选择上传还是下载,客户端必须先把user_choice发送给服务器,服务器才能根据选择执行对应处理。原代码中上传分支直接发送文件,跳过了发送操作选择的步骤,这是核心问题。
2. 修复Switch Case的贯穿问题
所有case分支结束后必须添加break;,否则代码会继续执行后续case的逻辑,导致流程混乱。
3. 服务器端同步修复Switch Case贯穿
服务器的switch同样需要添加break,避免执行完一个case后自动跑下一个case的代码。
修改后的客户端代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define BUFFER 1024 void send_file(FILE *fp, int sockfd) { int n; char data[BUFFER] = {0}; while(fgets(data, BUFFER, fp) != NULL) { if (send(sockfd, data, strlen(data), 0) == -1) { perror("[-]Error in sending file."); exit(1); } bzero(data, BUFFER); } // 发送结束标记,告诉服务器文件传输完成 send(sockfd, "EOF", 3, 0); } int main() { char *ip = "127.0.0.1"; int port = 8080; int sock, user_choice; struct sockaddr_in addr; char file[50]; FILE *fp; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("[-]Socket error"); exit(1); } printf("[+]Socket created\n"); memset(&addr, '\0', sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("[-]Connection error"); exit(1); } printf("Connected to the server\n"); printf("What do you want to do?\n1.Upload a file\n2.Download a file\n"); scanf("%d", &user_choice); // 先发送操作选择给服务器 write(sock, &user_choice, sizeof(user_choice)); switch(user_choice) { case 1: printf("Input name of file to be uploaded:\n"); scanf("%s", file); fp = fopen(file, "r"); if (fp == NULL) { perror("[-]Error in reading file."); exit(1); } send_file(fp, sock); printf("[+]File data sent successfully.\n"); fclose(fp); break; // 避免贯穿到case2 case 2: printf("Preparing to download file from server...\n"); // 这里可扩展下载逻辑:接收服务器发送的文件 break; // 避免后续逻辑串入 default: printf("Invalid choice!\n"); close(sock); exit(1); } close(sock); return 0; }
修改后的服务器端代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define BUFFER 1024 void write_file(int sock) { int n; FILE *fp; char *filename = "recv.txt"; char buffer[BUFFER]; fp = fopen(filename, "w"); if (fp == NULL) { perror("[-]Error opening file"); return; } while (1) { n = recv(sock, buffer, BUFFER, 0); if (n <= 0) { break; } // 检查结束标记 if (strstr(buffer, "EOF") != NULL) { // 去掉EOF标记再写入 buffer[strlen(buffer)-3] = '\0'; fprintf(fp, "%s", buffer); break; } fprintf(fp, "%s", buffer); bzero(buffer, BUFFER); } printf("[+]File uploaded successfully.\n"); fclose(fp); } void send_file_to_client(int sock) { // 示例下载逻辑:发送指定文件给客户端 FILE *fp = fopen("server_file.txt", "r"); if (fp == NULL) { perror("[-]Error opening file to send"); send(sock, "ERROR", 5, 0); return; } char data[BUFFER] = {0}; while(fgets(data, BUFFER, fp) != NULL) { send(sock, data, strlen(data), 0); bzero(data, BUFFER); } send(sock, "EOF", 3, 0); fclose(fp); printf("[+]File sent to client successfully.\n"); } int main() { char *ip = "127.0.0.1"; int port = 8080; int server_sock, client_sock; struct sockaddr_in server_addr, client_addr; socklen_t addr_size; int user_choice; server_sock = socket(AF_INET, SOCK_STREAM, 0); if (server_sock < 0) { perror("[-]Socket error"); exit(1); } printf("[+]Socket created\n"); 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(ip); if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("[-]Bind error"); exit(1); } printf("[+]Bind successful\n"); listen(server_sock, 5); printf("Listening...\n"); while(1) { addr_size = sizeof(client_addr); client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_size); if (client_sock < 0) { perror("[-]Accept error"); continue; } printf("[+]Client connected\n"); // 读取客户端发送的操作选择 if (read(client_sock, &user_choice, sizeof(user_choice)) <= 0) { perror("[-]Failed to read user choice"); close(client_sock); continue; } switch(user_choice) { case 1: printf("User chose upload option\n"); write_file(client_sock); break; // 避免贯穿到case2 case 2: printf("User chose download option\n"); send_file_to_client(client_sock); break; // 避免后续逻辑串入 default: printf("Received invalid choice from client\n"); } close(client_sock); printf("[+]Client disconnected.\n"); } close(server_sock); return 0; }
内容的提问来源于stack exchange,提问作者Aziz37
相关产品推荐
相关产品推荐

