Reputation: 43
I am having some trouble while using a custom definition of message struct in message queues. I am building a chat app between a client and a server. The client is sending a message, while the server is receiving the msg and printing it.
This is the server side code -
#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);
}
This is the client side -
#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");
}
My doubt is that it prints the msg.buffer data on server side alright, but fails to print anything for msg.header and prints 0 for msg.pid. Is this issue because of the structure of MESSAGE. Also, is the "size_t msgsz" parameter in msgsnd correct? TIA
Upvotes: 0
Views: 964
Reputation: 7973
According to the manpage, the msgsz
parameter is the size of the message buffer minus the mtype
. So using sizeof(msg)
is not correct, it will cause msgsnd()
to read beyond the end of the variable msg
. Also, it will cause the server to fail, since the server only expects to receive MAX
bytes (again, excluding mtype
).
I would avoid adding multiple member variables to struct msgbuf
, and instead just add one member that is either a char
array big enough to hold whatever data you want to send, or another struct
. For example:
#define MAX 200
#define SERVER 1L
struct payload {
char buffer[MAX];
char header[20];
long pid;
};
struct msgbuf {
long gid;
struct payload payload;
};
And then you can use it like so in the client:
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) ...
And like so in the server:
struct msgbuf msg;
if (msgrcv(mid_server, &msg, sizeof msg.payload, SERVER, 0) == -1) ...
Note the similarity in the calls to msgsnd()
and msgrcv()
.
Be aware of alignment restrictions, if you have any member in struct payload
that has alignment restrictions larger than those of gid
, it might cause payload
to not follow immediately after gid
. The msgsz
parameter should take this into account. However, the above code should be fine.
Upvotes: 1