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

使用SIGUSR1、SIGUSR2传输二进制数据时接收异常如何解决

问题根因
  • 服务端仅调用1次pause(),只能捕获单次信号,收到第一个信号后程序停止等待,剩余6个bit的信号无法被接收
  • 信号默认不支持排队,相同信号连续发送时会被合并丢弃,客户端无同步直接连发7个信号大概率会丢失中间信号
  • printf是不可重入函数,在信号处理函数内直接调用可能触发未知异常
  • 收发双方没有同步机制,发送节奏不匹配进一步加剧信号丢失
修复方案

服务端修改逻辑

  1. 新增循环等待逻辑,直到收满单个字符对应的7位二进制位再停止
  2. 使用volatile sig_atomic_t类型的原子变量存储信号传递的bit数据,避免读写过程被信号打断出现数据错误
  3. 将打印操作移出信号处理函数,收满所有bit后统一输出
  4. 每处理完一个bit向客户端发送确认信号,通知客户端可以发送下一个bit

服务端示例代码:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

volatile sig_atomic_t current_bit;
volatile sig_atomic_t bit_received = 0;

void my_handler(int signum) {
    if (signum == SIGUSR1) {
        current_bit = 1;
    } else if (signum == SIGUSR2) {
        current_bit = 0;
    }
    bit_received = 1;
}

int main(int argc, char *argv[]) {
    int bit_cnt = 0;
    char res[8] = {0};
    pid_t client_pid = atoi(argv[1]); // 启动时传入客户端PID即可适配非父子进程场景

    signal(SIGUSR1, my_handler);
    signal(SIGUSR2, my_handler);
    printf("服务端PID:%d\n", getpid()); // 打印PID供客户端传入

    while (bit_cnt < 7) {
        pause();
        if (bit_received) {
            res[bit_cnt] = current_bit ? '1' : '0';
            bit_cnt++;
            bit_received = 0;
            kill(client_pid, SIGUSR1); // 发送确认信号给客户端
        }
    }
    printf("收到二进制串:%s\n", res);
    return 0;
}

客户端修改逻辑

新增等待确认逻辑,每发送一个信号后阻塞等待服务端的确认回执,收到回执后再发送下一个bit,避免连续发信号导致丢失。

客户端示例代码:

#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

unsigned char target = 'g';
// 空确认信号处理函数,仅用来唤醒pause()
void ack_handler(int signum) {}

int main(int argc, char *argv[]) {
    pid_t server_pid = atoi(argv[1]);
    signal(SIGUSR1, ack_handler);
    printf("客户端PID:%d\n", getpid()); // 打印PID供服务端传入

    for (int i = 6; i >= 0; i--) {
        int bit = (target >> i) & 1;
        if (bit) {
            kill(server_pid, SIGUSR1);
        } else {
            kill(server_pid, SIGUSR2);
        }
        pause(); // 等待服务端确认后再发下一个
    }
    return 0;
}
补充说明

如果需要传输完整字符串,可以约定传输结束标识(比如连续发送8个0作为结束位),服务端收到结束标识后再停止循环即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 04:36:03