You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单线程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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:50:36