IPC消息队列中msg的结构

问题描述

我在消息队列中使用消息结构的自定义定义时遇到了一些问题。我正在客户端和服务器之间构建一个聊天应用程序。客户端正在发送消息,而服务器正在接收消息并打印出来。

这是服务器端代码-

#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,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

解决方法

根据manpagemsgsz参数是消息缓冲区的大小减去mtype。因此使用 sizeof(msg) 是不正确的,它会导致 msgsnd() 读取超出变量 msg 的末尾。此外,它会导致服务器失败,因为服务器只希望接收 MAX 字节(同样,不包括 mtype)。

我会避免向 struct msgbuf 添加多个成员变量,而是只添加一个成员,该成员要么是一个 char 数组,其大小足以容纳您想要发送的任何数据,或者另一个 {{1} }.例如:

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,SERVER,0) == -1) ... msgsnd() 的调用的相似性。

注意对齐限制,如果您在 msgrcv() 中有任何成员的对齐限制大于 struct payload 的对齐限制,可能会导致 gid 不会紧跟在 {{1 }}。 payload 参数应考虑到这一点。不过,上面的代码应该没问题。