如何使用time函数并通过命名管道传递时间:客户端服务器通信时间无法在服务器端显示问题排查
问题分析与修复方案
咱们来拆解一下你代码里的几个关键问题,这些问题直接导致服务器端看不到时间数据:
1. 客户端写入时间时的指针错误
你在客户端里写时间的代码是:
write(fd, (void*) current_time, sizeof(current_time));
这里的问题是,current_time是time_t类型的变量,你直接把它转换成void*,相当于把时间的数值当成了内存地址——这会让write尝试读取这个"地址"处的无效内存,属于未定义行为,根本没把实际的时间值写到管道里。
正确的写法应该是传递current_time的地址:
write(fd, ¤t_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, ¤t_time, sizeof(current_time)); close(fd); return 0; }
额外提示
- 编译时直接用
gcc server.c -o server和gcc client.c -o client即可,不需要额外链接库; - 测试时先启动服务器,再运行客户端,输入文本后回车,服务器就能同时显示文本和时间了;
- 如果管道已经存在,再次运行服务器会报错,可以先删除
/tmp/myfifo,或者在代码里处理EEXIST错误(比如忽略,因为管道已经存在可以直接使用)。
内容的提问来源于stack exchange,提问作者alkantra1




