IPC消息队列中msg的结构
Posted
技术标签:
【中文标题】IPC消息队列中msg的结构【英文标题】:structure of msg in IPC message queues 【发布时间】:2021-06-24 20:58:33 【问题描述】:我在消息队列中使用消息结构的自定义定义时遇到了一些麻烦。我正在客户端和服务器之间构建一个聊天应用程序。客户端正在发送消息,而服务器正在接收消息并打印它。
这是服务器端代码 -
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#define MAX 200
#define SERVER 1L
typedef struct
long gid;
char buffer[MAX];
char header[20];
long pid;
MESSAGE;
struct msqid_ds buf;
MESSAGE msg;
int mid_server, mid_client;
key_t key1, key2;
int client_id = 0;
int main()
//Creating a message queue
key1 = ftok(".", 'z');
msg.gid = 1;
if((mid_server = msgget(key1, IPC_CREAT | 0666))<0)
printf("Error Creating Message Queue\n");
exit(-1);
//Receiving message from client, throws and error if input is invalid
if(msgrcv(mid_server, &msg, MAX, SERVER, 0)<0)
perror("msgrcv");
exit(-1);
//Server displays received message
printf("SERVER receives: %s\n", msg.buffer);
printf("SERVER receives---: %s\n", msg.header);
printf("SERVER receives: %ld\n", msg.pid);
这是客户端 -
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#define MAX 200
#define SERVER 1L
typedef struct
long gid;
char buffer[MAX];
char header[20];
long pid;
MESSAGE;
int mid_client, mid_server;
key_t key1,key2;
MESSAGE msg;
int client_id = -1;
int main()
//Creating a message queue
key1 = ftok(".", 'z');
if((mid_server = msgget(key1, IPC_CREAT | 0666))<0) //server receives here
printf("Error Creating Message Queue\n");
exit(-1);
printf("%d\n", mid_server);
fgets(msg.buffer, MAX, stdin);
msg.gid = SERVER;
strcpy(msg.header, "msg");
msg.pid = 2;
if(msgsnd(mid_server, (struct MESSAGE*)&msg, sizeof(msg), IPC_NOWAIT)==-1)
perror("msgsnd");
exit(-1);
printf("message sent\n");
我怀疑它在服务器端打印 msg.buffer 数据没问题,但无法为 msg.header 打印任何内容,并且为 msg.pid 打印 0。这个问题是不是因为MESSAGE的结构。另外,msgsnd 中的“size_t msgsz”参数是否正确? TIA
【问题讨论】:
【参考方案1】:根据manpage,msgsz
参数是消息缓冲区的大小减去mtype
。所以使用sizeof(msg)
是不正确的,会导致msgsnd()
读取到变量msg
之外。此外,这将导致服务器失败,因为服务器只期望接收MAX
字节(同样,不包括mtype
)。
我会避免向struct msgbuf
添加多个成员变量,而只需添加一个成员,该成员要么是char
数组,大到足以容纳您要发送的任何数据,要么是另一个struct
。例如:
#define MAX 200
#define SERVER 1L
struct payload
char buffer[MAX];
char header[20];
long pid;
;
struct msgbuf
long gid;
struct payload payload;
;
然后你就可以在客户端这样使用它了:
struct msgbuf msg;
msg.gid = SERVER;
fgets(msg.payload.buffer, sizeof msg.payload.buffer, stdin);
strncpy(msg.payload.header, sizeof msg.payload.header, "msg");
msg.payload.pid = 2;
if (msgsnd(mid_server, &msg, sizeof msg.payload, IPC_NOWAIT) == -1) ...
在服务器中也是这样:
struct msgbuf msg;
if (msgrcv(mid_server, &msg, sizeof msg.payload, SERVER, 0) == -1) ...
注意调用msgsnd()
和msgrcv()
的相似之处。
注意对齐限制,如果struct payload
中的任何成员的对齐限制大于gid
的对齐限制,则可能导致payload
在gid
之后无法立即关注。 msgsz
参数应考虑到这一点。不过上面的代码应该没问题。
【讨论】:
是的,这很有效,非常感谢。被这个问题困扰了一天。以上是关于IPC消息队列中msg的结构的主要内容,如果未能解决你的问题,请参考以下文章