消息队列Sender程序发送字节数显示为0问题求助
解决Sender程序发送字节数显示为0的问题
代码中的关键错误
- 文件大小未初始化且未获取:
fileSize初始值为-1,循环条件totalBytesRead < fileSize(0 < -1)永远不成立,导致读取文件的循环完全未执行,totalBytesRead始终为0。 - read函数参数错误:read的第三个参数是最大读取字节数,你传入了初始为0的
bytesRead,导致首次读取0字节,后续逻辑全部混乱。 - mq_send参数顺序完全错误:mq_send的正确参数顺序为
mq_send(队列ID, 缓冲区指针, 消息长度, 优先级),你颠倒了缓冲区和长度的位置,还错误传入4096作为固定长度。 - 循环计数逻辑错误:将read的返回值直接赋值给
totalBytesRead,后续又执行totalBytesRead += bytesRead,导致计数完全错误;同时判断文件结束的条件逻辑颠倒。 - 未检查mq_open返回值:如果消息队列不存在,mq_open会返回-1,但你未做错误处理,程序会继续执行无效逻辑。
- 未实现结束标记消息:作业要求发送优先级为2的空消息告知接收方传输结束,代码中未完成该逻辑。
- 硬编码队列名称:定义了宏
MSQ_NAME却在mq_open中硬编码路径,导致代码一致性问题。 - 缺少bool类型依赖:使用
bool类型但未包含stdbool.h头文件,可能引发编译错误。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <mqueue.h> #include <unistd.h> #include <stdbool.h> // 新增:支持bool类型 #define MSQ_NAME "/cpsc351queue" int main(int argc, char** argv) { off_t fileSize = 0; char buff[4096]; mqd_t qid = -1; int totalBytesSent = 0; // 重命名为更准确的语义 ssize_t bytesRead = 0; // 匹配read返回值的ssize_t类型 bool finishedReading = false; mq_attr attr; attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = 4096; attr.mq_curmsgs = 0; // 参数合法性检查 if(argc < 2) { fprintf(stderr, "USAGE: %s <FILE NAME>\n", argv[0]); exit(1); } // 打开目标文件 int fd = open(argv[1], O_RDONLY); if(fd < 0) { perror("open"); exit(1); } // 获取文件大小 struct stat fileStat; if(fstat(fd, &fileStat) < 0) { perror("fstat"); close(fd); exit(1); } fileSize = fileStat.st_size; // 打开消息队列:仅写模式,队列不存在则报错 qid = mq_open(MSQ_NAME, O_WRONLY); if(qid == (mqd_t)-1) { perror("mq_open"); close(fd); exit(1); } // 循环读取文件并发送消息 while(!finishedReading) { // 每次最多读取4096字节 bytesRead = read(fd, buff, sizeof(buff)); if(bytesRead < 0) { perror("read"); mq_close(qid); close(fd); exit(1); } else if(bytesRead == 0) { // 文件读取完毕 finishedReading = true; break; } // 发送读取到的内容,优先级设为1 if(mq_send(qid, buff, bytesRead, 1) < 0) { perror("mq_send"); mq_close(qid); close(fd); exit(1); } totalBytesSent += bytesRead; } // 发送优先级为2的空消息,告知接收方传输结束 if(mq_send(qid, "", 0, 2) < 0) { perror("mq_send (end marker)"); mq_close(qid); close(fd); exit(1); } fprintf(stderr, "Sent a total of %d bytes\n", (int)totalBytesSent); // 关闭所有资源 mq_close(qid); close(fd); return 0; }
修复核心说明
- 正确获取文件大小:通过
fstat获取打开文件的实际大小,确保读取循环能正常执行。 - 修正系统调用参数:调整read和mq_send的参数顺序与取值,符合函数原型要求。
- 修复计数逻辑:用
totalBytesSent累计实际发送的字节数,每次读取后累加有效读取长度。 - 完善错误处理:对所有系统调用的返回值做检查,确保队列不存在时直接报错退出,符合作业要求。
- 实现结束标记:补充发送优先级为2的空消息逻辑,完成作业要求的传输结束通知。
- 类型匹配与代码一致性:修正变量类型,使用宏定义的队列名称,避免硬编码错误。
内容的提问来源于stack exchange,提问作者Jose
相关产品推荐
相关产品推荐

