You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用time函数并通过命名管道传递时间:客户端服务器通信时间无法在服务器端显示问题排查

问题分析与修复方案

咱们来拆解一下你代码里的几个关键问题,这些问题直接导致服务器端看不到时间数据:

1. 客户端写入时间时的指针错误

你在客户端里写时间的代码是:

write(fd, (void*) current_time, sizeof(current_time));

这里的问题是,current_timetime_t类型的变量,你直接把它转换成void*,相当于把时间的数值当成了内存地址——这会让write尝试读取这个"地址"处的无效内存,属于未定义行为,根本没把实际的时间值写到管道里。

正确的写法应该是传递current_time的地址:

write(fd, &current_time, sizeof(current_time));

2. 服务器端没有读取时间数据

你的服务器端每次循环只读取一次80字节(str的大小),但客户端实际上向管道写了两次数据:一次是fgets读取的字符串,一次是时间值。服务器只读取了第一次的字符串,时间数据被留在管道里,下次循环才会被读取,但你又没处理这部分数据,自然看不到输出。

另外你每次循环都打开、关闭管道,这会导致管道在客户端关闭后,服务器的read会返回0(表示EOF),咱们需要调整读取逻辑,先读字符串,再读时间数据。

3. 字符串写入长度错误

客户端里用write(fd, str, sizeof(str))写入字符串,sizeof(str)是80,但fgets读取的实际字符串长度可能远小于80,这样会把str里未初始化的垃圾数据也写到管道里。正确的做法是只写入实际读取的字符数:

write(fd, str, strlen(str));

(记得要包含<string.h>头文件来使用strlen

4. 服务器端需要解析时间数据

服务器读取到的time_t是一个数值,直接打印的话是一串数字,你需要用ctime()或者localtime()把它转换成人类可读的时间字符串。


修复后的完整代码

服务器端代码

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>

int main() {
    char *pathname = "/tmp/myfifo";
    // 检查mkfifo是否成功,避免重复创建的错误
    if (mkfifo(pathname, 0666) == -1) {
        perror("mkfifo failed");
        return 1;
    }

    char str[80];
    time_t received_time;

    for(;;) {
        int opn = open(pathname, O_RDONLY);
        if (opn == -1) {
            perror("open failed");
            continue;
        }

        // 先读取字符串,确保结尾加'\0'避免乱码
        ssize_t str_len = read(opn, str, sizeof(str) - 1);
        if (str_len > 0) {
            str[str_len] = '\0';
            printf("Received text: %s", str);
        }

        // 再读取时间数据
        ssize_t time_len = read(opn, &received_time, sizeof(received_time));
        if (time_len == sizeof(received_time)) {
            printf("Received time: %s", ctime(&received_time));
        }

        close(opn);
    }
    return 0;
}

客户端代码

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>

int main() {
    char *pathname = "/tmp/myfifo";
    time_t current_time = time(0);
    char str[80];

    int fd = open(pathname, O_WRONLY);
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    fgets(str, 80, stdin);
    // 只写入实际读取的字符串长度
    write(fd, str, strlen(str));
    // 写入时间变量的地址
    write(fd, &current_time, sizeof(current_time));

    close(fd);
    return 0;
}

额外提示

  • 编译时直接用gcc server.c -o servergcc client.c -o client即可,不需要额外链接库;
  • 测试时先启动服务器,再运行客户端,输入文本后回车,服务器就能同时显示文本和时间了;
  • 如果管道已经存在,再次运行服务器会报错,可以先删除/tmp/myfifo,或者在代码里处理EEXIST错误(比如忽略,因为管道已经存在可以直接使用)。

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

火山引擎 最新活动