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

C语言中信号量未按预期工作的客户端/服务器程序问题

客户端/服务器程序消息处理异常

我正在开发一个客户端/服务器程序,服务器通过信号量避免同时接收多条消息出错,但实际运行不符合预期:

测试场景与异常表现

  1. 测试cli_test.c,发送num1=10、num2=-1:

    • 实际输出:

      Client: message received :20.000000.
      Client: message received :-1.

    • 预期输出:

      Client: message received :20.000000.
      Client: message received :Invalid number.

  2. 修改为num1=-12、num2=-1:

    • 实际输出:

      Client: message received :-1.
      Client: message received :Invalid number.

    • 预期输出:两条Client: message received :Invalid number.
  3. 修改为num1=12、num2=1:

    • 实际输出:

      Client: message received :24.000000.
      Client: message received :1.000000.

    • 预期输出:24.000000和2.000000

可见服务器仅正确处理一条消息,另一条未计算直接返回原数值。

服务器代码(server.c)

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/sem.h>
#include <time.h>
#include <semaphore.h>

typedef struct {
    long id;
    char mes[20];
} message;

double calculate(int num){
    return num*2;
}

struct sembuf semaphore_operations[1];

int main() {
    
    // key
    key_t cle = ftok(".", 0);
    if (cle == -1) {
        perror("ftok");
        return -1;
    }

    // message queue
    int msqId = msgget(cle, IPC_CREAT | 0700);
    if (msqId == -1) {
        perror("msgget");
        return -1;
    }

    // semaphore
    int semId = semget(cle, 1, IPC_CREAT | 0700);
    if (semId == -1) {
        perror("semget");
        return -1;
    }

    if (semctl(semId, 0, SETVAL, 1) == -1) {
        perror("semctl");
        return -1;
    }

    semaphore_operations[0].sem_num = 0;
    semaphore_operations[0].sem_flg = 0;

    message mes;

    while (1) {
        
        semaphore_operations[0].sem_op = -1;
        if (semop(semId, semaphore_operations, 1) == -1) {
            perror("semop");
            return -1;
        }

        // wait for message (blocked)
        int received = msgrcv(msqId, &mes, sizeof(message) - sizeof(long), 0, 0);
        if (received == -1) {
            perror("msgrcv");
            return -1;
        }

        int num_mat = atoi(mes.mes);
        printf("Server: message received :%d.\n", num_mat);

        if(num_mat > 0) {
            double result = calculate(num_mat);
            char result_str[20] = "";
            sprintf(result_str, "%f", result);
            strcpy(mes.mes, result_str);

            int sent = msgsnd(msqId, &mes, sizeof(message) - sizeof(long), 0);
            if (sent == -1) {
                perror("msgsnd");
                return -1;
            }
            printf("Server: message sent.\n");
        }
        else {
            strcpy(mes.mes, "Invalid number");
            int sent = msgsnd(msqId, &mes, sizeof(message)-sizeof(long), 0);
        
            if(sent == -1){
                perror("msgsnd");
                return -1;
            }
        }
        
        // signal the semaphore
        semaphore_operations[0].sem_op = 1;
        if (semop(semId, semaphore_operations, 1) == -1) {
            perror("semop");
            return -1;
        }
    }

    // remove when server shut down
    msgctl(msqId, IPC_RMID, NULL);
    semctl(semId, 0, IPC_RMID, 0);

    return 0;
}

客户端测试代码(cli_test.c)

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/sem.h>
#include <time.h>
#include <semaphore.h>
#include <pthread.h>

typedef struct {
    long id;
    char mes[20];
} message;

void* client_thread(void* arg) {
    
    key_t cle = ftok(".", 0);
    if (cle == -1) {
        perror("ftok");
        pthread_exit(NULL);
    }

    int msqId = msgget(cle, 0);
    if (msqId == -1) {
        perror("msgget");
        pthread_exit(NULL);
    }

    message mes;
    mes.id = 1;
    int num = *((int*) arg);
    sprintf(mes.mes, "%d", num);

    // send message to the server
    int sent = msgsnd(msqId, &mes, sizeof(message) - sizeof(long), 0);
    if (sent == -1) {
        perror("msgsnd");
        pthread_exit(NULL);
    }

    // receive the result
    message result;
    int received = msgrcv(msqId, &result, sizeof(message) - sizeof(long), 0, 0);
    if (received == -1) {
        perror("msgrcv");
        pthread_exit(NULL);
    }
    
    printf("Client: message received :%s.\n", result.mes);

    pthread_exit(NULL);
}

int main() {
    
    pthread_t client1, client2;
    int num1 = 10, num2 = -1;

    if (pthread_create(&client1, NULL, client_thread, &num1) != 0) {
        perror("pthread_create");
        return -1;
    }

    if (pthread_create(&client2, NULL, client_thread, &num2) != 0) {
        perror("pthread_create");
        return -1;
    }

    pthread_join(client1, NULL);
    pthread_join(client2, NULL);

    return 0;
}

内容的提问来源于stack exchange,提问作者Hangel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:30:40