UNIX message queue msgrcv failed to receive message - c

Dear Friends,
Any idea why the msgrcv is receiving a blank buffer?
Here is the code:
enter code here
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
typedef struct mymsg {
long mtype;
char mtext[24];
}mymsg;
int main()
{
int msqid;
mymsg msg,buff;
msqid=msgget(IPC_PRIVATE,IPC_CREAT|IPC_EXCL);
if(msqid==-1){
perror("FAiled to create message queue\n");
}
else{
printf("Message queue id:%u\n",msqid);
}
msg.mtype=1;
strcpy(msg.mtext,"This is a message");
if(msgsnd(msqid,&msg,sizeof(msg.mtext),0)==-1){
perror("msgsnd failed:");
}
else{
printf("Message sent successfully\n");
}
//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
// msgrcv(msqid,buff.mtext,sizeof(msg.mtext),1,0); This was error
msgrcv(msqid,&buff,sizeof(msg.mtext),1,0); // This is correct (Thanks to Erik)
printf("The message received is: %s\n",buff.mtext);
}
Output:
[root#dhcppc0 message_queue]# ./a.out
Message queue id:294919
Message sent successfully
The message received is:
1,1 Top

msgbuf.mtype must be set to 1 - since you're telling msgrcv that you want messages of type 1.
Alternatively, you could set msgbuf.mtype to any positive value, and then tell msgrcv that you want any message type by passing 0 as the msgtyp argument.
Also, msgrcv expects a pointer to a msgbuf:
msgrcv(msqid,&buff,sizeof(msg.mtext),1,0);
EDIT: Tested working source:
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
typedef struct mymsg {
long mtype;
char mtext[24];
}mymsg;
int main()
{
int msqid;
mymsg msg,buff;
msqid=msgget(IPC_PRIVATE,IPC_CREAT|IPC_EXCL);
if(msqid==-1){
perror("FAiled to create message queue\n");
}
else{
printf("Message queue id:%u\n",msqid);
}
msg.mtype=1; // was there failed to copy
strcpy(msg.mtext,"This is a message");
if(msgsnd(msqid,&msg,sizeof(msg.mtext),0)==-1){
perror("msgsnd failed:");
}
else{
printf("Message sent successfully\n");
}
//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgrcv(msqid,&buff,sizeof(msg.mtext),1,0);
printf("The message received is: %s\n",buff.mtext);
}

Related

Sending a process id from client to server

My task is to write a client program that writes a struct with a privateFIFO name (FIFO_XXXX, where XXXX is the pid that we get from the getpid( ) function) to the server. Then, have the server read the privateFIFO name and write a message back to the client. i.e., Read the message and print it on the client side. I am having trouble sending the FIFO_XXXX to the server program and also writing a message from the server back to client.
client code:
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
struct values
{
char privateFIFO[14];
int intbuff;
}input;
int fda; // common FIFO to read to write to server
int fdb; // Private FIFO to read from server
int clientID;
int retbuff;
char temp[14];
clientID = getpid();
strcpy(input.privateFIFO, "FIFO_");
sprintf(temp, "%d", clientID);
strcat(input.privateFIFO, temp);
printf("\nFIFO name is %s", input.privateFIFO);
// Open common FIFO to write to server
if((fda=open("FIFO_to_server", O_WRONLY))<0)
printf("cant open fifo to write");
write(fda, &input, sizeof(input)); // write the struct to the server
close(fda);
// Open private FIFO to read
if((fdb=open(input.privateFIFO, O_RDONLY))<0)
read(fdb, &retbuff, sizeof(retbuff));
printf("\nAll done!\n");
close(fdb);
}
server code:
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
struct values
{
char privateFIFO[14];
int intbuff;
}input;
int main (void)
{
int fda; //common FIFO to read from client
int fdb; //private FIFO to write to client
int retbuff;
int output;
// create the common FIFO
if ((mkfifo("FIFO_to_server",0666)<0 && errno != EEXIST))
{
perror("cant create FIFO_to_server");
exit(-1);
}
// open the common FIFO
if((fda=open("FIFO_to_server", O_RDONLY))<0)
printf("cant open fifo to write");
output = read(fda, &input, sizeof(input));
// create the private FIFO
if ((mkfifo(input.privateFIFO, 0666)<0 && errno != EEXIST))
{
perror("cant create privateFIFO_to_server");
exit(-1);
}
printf("Private FIFO received from the client and sent back from server is: %d", output);
//open private FIFO to write to client
if((fdb=open(input.privateFIFO, O_WRONLY))<0)
printf("cant open fifo to read");
write(fdb, &retbuff, sizeof(retbuff));
close(fda);
unlink("FIFO_to_server");
close(fdb);
unlink(input.privateFIFO);
}
Use IPC message Queues. It better and simple. Indeed, This mechanism manages synchronization between read and write operations, concurrent access, ...:
The Writer Process:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// structure for message queue
struct mesg_buffer {
long mesg_type;
char mesg_text[100];
} message;
int main()
{
key_t QueueKey;
int msgid;
// ftok : generate a unique OPC key
QueueKey = ftok("FIFO_XXXX", 65);
// msgget creates a message queue and returns identifier
msgid = msgget(QueueKey, 0666 | IPC_CREAT);
// Sending Data
message.mesg_type = 1;
printf("Write Data : ");
gets(message.mesg_text);
// msgsnd : Send message to the queue
msgsnd(msgid, &message, sizeof(message), 0);
// display the message
printf("Data send is : %s \n", message.mesg_text);
return 0;
}
The Reader Process:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// structure for message queue
struct mesg_buffer {
long mesg_type;
char mesg_text[100];
} message;
int main()
{
key_t QueueKey;
int msgid;
// ftok to generate unique key
QueueKey = ftok("FIFO_XXXX", 65);
// msgget creates a message queue and returns identifier
msgid = msgget(QueueKey, 0666 | IPC_CREAT);
// msgrcv to receive message
msgrcv(msgid, &message, sizeof(message), 1, 0);
// display the message
printf("Data Received is : %s \n", message.mesg_text);
// IPC_RMID : destroy the message queue
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
Remarque:
Be aware that a process can be both writer and reader. To do this, two message queues must be created for each process. the first allows for example to receive, the second to write. If you really want to separate read / write spaces for each process.

Message queue is giving me an invalid argument

I'm having some trouble with my code. It should create a message queue and send a message, than wait some time for another program to receive that message and answer. The problem is, when I run it, I get an invalid argument both on the msgsnd and on the msgrcv.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/msg.h>
typedef struct my_msg{
long type;
char text[100];
char sqdr;
}message;
static void score(int messagge_id, char* A_B){
message send;
send.type=1;
strcpy(send.text, "Try to score");
send.sqdr = *A_B;
if((msgsnd(messagge_id, &send, sizeof(send), 0))<0)perror("Error msgsnd\n");
sleep(3);
if((msgrcv(messagge_id, &send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n");
int test=atoi(send.text);
printf("%d\n", test);
}
int main(){
int caso, key;
char team= 'A';
key=1234;
int msg_id=msgget(key, S_IRUSR|S_IWUSR);
printf("Try function score\n");
score(msg_id, &team);
printf("After score\n");
return 0;
}
You need to ensure that the message queue is created. You either use the key IPC_PRIVATE or you add IPC_CREAT to the flags. You also need to try to read the message correctly. You sent a 'type 1' message and attempted to read a 'type 4' message, so the read hangs.
This code also removes the message queue. That's not critical if it is a private queue (such queues are deleted when the program terminates), but it is important for queues using IPC_CREAT and a user-defined key. (I also changed the message text so that atoi() returned something more interesting — and convincing — than zero. The code also uses separate send and receive buffers so that we know the code is not cheating and reusing data already in the buffer.)
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <fcntl.h>
typedef struct my_msg
{
long type;
char text[100];
char sqdr;
} message;
static void score(int messagge_id)
{
message send;
message recv;
send.type = 1;
strcpy(send.text, "47 tries to score");
send.sqdr = 'A';
if ((msgsnd(messagge_id, &send, sizeof(send), 0)) < 0)
perror("Error msgsnd");
printf("Dozing...\n");
sleep(3);
printf("Unslumbering...\n");
if ((msgrcv(messagge_id, &recv, sizeof(recv), -4, 0)) == -1)
perror("Error msgrcv");
int test = atoi(recv.text);
printf("%d\n", test);
}
int main(void)
{
int key = 1234;
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
// int key = IPC_PRIVATE;
// int flags = S_IRUSR|S_IWUSR;
int msg_id = msgget(key, flags);
if (msg_id < 0)
perror("Error msgget");
else
{
printf("Try function score\n");
score(msg_id);
printf("After score\n");
if (msgctl(msg_id, IPC_RMID, 0) < 0)
perror("Error msgctl");
}
return 0;
}
Sample output:
Try function score
Dozing...
Unslumbering...
47
After score
There's a 3 second pause between 'Dozing' and 'Unslumbering', of course.
use like this:-
if((msgsnd(messagge_id, (void *)&send, sizeof(send), 0))<0)perror("Error msgsnd\n");
if((msgrcv(messagge_id, (void *)&send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n");

Blank msgrcv buffer

I tried to run the message queue program of a telephonic conversation between a caller and a receiver given here with the correction stated.I keep getting the following result:
./caller
Caller Program
<<<
CALLER:Hello!!
while running the caller executable.The message buffer while receiving is empty.I don't know why.Please help!!
The caller.c is:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
struct msgbuf
{
long mtype;
char mtext[140];
}msg_buf;
int send_msg_id,receive_msg_id;
key_t send_key,receive_key;
void *send_message(void *a)
{
send_key=ftok("Caller1.c",'A');
if (send_key==-1)
{
printf("\nCaller send key error");
exit(1);
}
send_msg_id=msgget(send_key,0666 | IPC_CREAT);
if (send_msg_id==-1)
{
printf("\nCaller send msgget error");
exit(1);
}
printf("\nCALLER:");
while (fgets(msg_buf.mtext,sizeof(msg_buf.mtext),stdin)!=NULL)
{
msg_buf.mtype=1;
int len=strlen(msg_buf.mtext);
if (msg_buf.mtext[len-1]=='\n');
msg_buf.mtext[len-1]='\0';
if (msgsnd(send_msg_id,&msg_buf,len+1,0)==-1)
printf("\nMsg sending error\n");
}
int i=0;
while(i<9999)
i++;
msgctl(send_msg_id,IPC_RMID,NULL);
return;
}
void *receive_message(void *a)
{
receive_key=ftok("Receiver1.c",'B');
if (receive_key==-1)
{
printf("\nReceiver send key error");
exit(1);
}
send_msg_id=msgget(receive_key,0777|IPC_CREAT);
if (receive_msg_id==-1)
{
printf("\nCaller msgrcv error");
exit(1);
}
printf("\n<<<");
while(1)
{
if(msgrcv(receive_msg_id,&msg_buf,sizeof(msg_buf.mtext),1,0)!=-1)
printf("<<<%s\n",msg_buf.mtext);
}
return;
}
void initialize()
{
pthread_t send_thread,receive_thread;
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}
int main()
{
printf("\nCaller Program\n");
initialize();
return 0;
}

IPC mechanism using message queues in C

I am trying to implement a IPC mechanism for telephone conversation using message queues in C. I have created two .c files, one for caller and one for receiver. In each .c file i have created two threads , one for sending messages and another for receiving messages. Each thread creates its message queue. The send message thread from caller and the receive message thread from receiver share the same queue and same for the other.
The message queues are being created but whenever i enter some message to be sent , it fails. The msgsnd(-,-,-,-) always returns -1.
The caller.c file is as follows :
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
struct msgbuf
{
long mtype;
char mtext[50];
}SEND_BUFFER,RECEIVE_BUFFER;
int send_msgQ_id, receive_msgQ_id;
key_t send_key,receive_key;
void * send_message(void * a)
{
send_key = ftok("Caller.c", 'B');
if(send_key==-1)
{
printf("\n caller send key error");
exit(1);
}
send_msgQ_id = msgget(send_key, 0666 | IPC_CREAT);
if(send_msgQ_id==-1)
{
printf("\n caller send msgget error");
exit(1);
}
printf("\n Enter lines of text, ^D to quit:\n");
while(fgets(SEND_BUFFER.mtext, sizeof(SEND_BUFFER.mtext), stdin) != NULL)
{
SEND_BUFFER.mtype = 0;
int len = strlen(SEND_BUFFER.mtext);
if (SEND_BUFFER.mtext[len-1] == '\n')
SEND_BUFFER.mtext[len-1] = '\0';
printf("\n Attemping to send %s\n", SEND_BUFFER.mtext);
if(msgsnd(send_msgQ_id, &SEND_BUFFER, len+1, 0)==-1)
printf("\n msg sendign error\n");
}
int i =0;
while(i<9999)
i++;
msgctl(send_msgQ_id, IPC_RMID, NULL);
return;
}
void * receive_message(void * a)
{
receive_key = ftok("Receiver.c", 'B');
if(receive_key==-1)
{
printf("\n caller receive key error");
exit(1);
}
receive_msgQ_id = msgget(receive_key, 0777 | IPC_CREAT);
if(receive_msgQ_id==-1)
{
printf("\n caller receive msgget error");
exit(1);
}
printf("\n Ready to receive ");
while(1)
{
if( msgrcv(receive_msgQ_id, &RECEIVE_BUFFER, sizeof(RECEIVE_BUFFER.mtext), 0, 0)!=-1)
printf("Received : %s\n", RECEIVE_BUFFER.mtext);
}
return;
}
void initialize()
{
pthread_t send_thread,receive_thread;
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}
int main()
{
printf("\n\n *** Caller Program ***\n");
initialize();
return 0;
}
The receiver.c file is as follows (it is similar to the caller.c file) :
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
struct msgbuf
{
long mtype;
char mtext[50];
}SEND_BUFFER,RECEIVE_BUFFER;
int send_msgQ_id, receive_msgQ_id;
key_t send_key,receive_key;
void * send_message(void * a)
{
send_key = ftok("Receiver.c", 'B');
if(send_key==-1)
{
printf("\n receiver send key error");
exit(1);
}
send_msgQ_id = msgget(send_key, 0777);
if(send_msgQ_id==-1)
{
printf("\n receiver msgget error ");
exit(1);
}
printf("\n Enter lines of text, ^D to quit:\n");
SEND_BUFFER.mtype = 0;
while(fgets(SEND_BUFFER.mtext, sizeof(SEND_BUFFER.mtext), stdin) != NULL)
{
int len = strlen(SEND_BUFFER.mtext);
if (SEND_BUFFER.mtext[len-1] == '\n')
SEND_BUFFER.mtext[len-1] = '\0';
msgsnd(send_msgQ_id, &SEND_BUFFER, len+1, 0);
}
int i =0;
while(i<9999)
i++;
msgctl(send_msgQ_id, IPC_RMID, NULL);
return;
}
void * receive_message(void * a)
{
receive_key = ftok("Caller.c", 'B');
if(receive_key==-1)
{
printf("\n receiver receiver key error");
exit(1);
}
receive_msgQ_id = msgget(receive_key, 0666);
if(receive_msgQ_id==-1)
{
printf("\n msgget error");
exit(1);
}
while(1)
{
if(msgrcv(receive_msgQ_id, &RECEIVE_BUFFER, sizeof(RECEIVE_BUFFER.mtext), 0, 0)==-1)
printf("\n msg receiving error");
else
printf("Received : %s\n", RECEIVE_BUFFER.mtext);
}
return;
}
void initialize()
{
pthread_t send_thread,receive_thread;
pthread_create(&receive_thread,NULL,receive_message,NULL);
pthread_create(&send_thread,NULL,send_message,NULL);
pthread_join(send_thread,NULL);
pthread_join(receive_thread,NULL);
return;
}
int main()
{
printf("\n\n *** Receiver Program ***\n");
initialize();
return 0;
}
I need that both the caller and sender can receive and send messages at their free will.
The errno you're getting indicates you're passing an invalid argument to msgsnd. According to the man page for msgsnd:
[EINVAL]
The value of msqid is not a valid message queue identifier, or the value of mtype is less than 1; or the value of msgsz is less than 0 or greater than the system-imposed limit.
Blockquote
My guess would be that msqid is the offending parameter. Either check the value in a debugger or print it out.
EDIT: Mike Wilkins spotted it. His comment:
mtype is likely the issue (not msqid). mtype needs to be > 0. The code
in the OP specifically sets it to 0

Basic unix server-client IPC(msg queue) issue

I'm working on a problem wich implies a basic running server client(done one before). the problem is that I run server than I run client. My msg Que is created i nboth client takes my char as input sends it, i get the confirmation print but my server msgrcv isn't responding.
s.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include "struc.h"
int main(){
int qt;
struct msg m;
qt = msgget(1271,IPC_CREAT|IPC_EXCL|0600);
if(qt < 0){ perror("Error MSGGET()\n");}
printf("msg queue created!\n");
if(msgrcv(qt,&m,sizeof(struct msg),0,0)<0){
perror("Msg recive error");
}
printf("msg recived!\n");
msgctl(qt,IPC_RMID,NULL);
return 0;
}
c.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include "struc.h"
int main(){
int qt;
struct msg m;
qt = msgget(1271,0);
if(qt < 0){ perror("~~~ Error MSGGET()\n");}
printf("msg created!\n");
printf("Enter one char: !\n");
scanf("%c",&m.c);
msgsnd(qt, &m,sizeof(struct msg),0);
printf("msg sent!\n");
return 0;
}
struc.h
struct msg{
long mtype;
// matrix M;
char c;
};
(By creating the 3 files you cna test it yourself. Any idea is welcome maybe i missed something)
You should do this to verify that sending doesn't fail.
if(msgsnd(qt, &m,sizeof(struct msg),0)) < 0) {
perror("Msg send error");
}
You should also heed the docs for msgsnd:
The msgp argument is a pointer to caller-defined structure of the
following general form:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
That is, you have to set the mtype in the message you send to be > 0. Currently it is uninitialized, so you should do:
m.mtype = 1;
if(msgsnd(qt, &m,sizeof(struct msg),0)) < 0) {
perror("Msg send error");
}

Resources