问题描述
我在消息队列中使用消息结构的自定义定义时遇到了一些问题。我正在客户端和服务器之间构建一个聊天应用程序。客户端正在发送消息,而服务器正在接收消息并打印出来。
这是服务器端代码-
#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
解决方法
根据manpage,msgsz
参数是消息缓冲区的大小减去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
参数应考虑到这一点。不过,上面的代码应该没问题。