I must say I have a hard time understanding why you are continuously opening and closing the message queue. Perhaps inefficiency is a vague concept to you.
I wrote a simpler program, albeit without the signal handling capabilities that you have in your program. Perhaps you can glean some ideas from this little app:
Code:
#define _XOPEN_SOURCE 600 /* for mq_timedreceive() */
#include <time.h>
#include <mqueue.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
bool quit = false;
void strip_newline(char* str);
void sigHandler(int sig);
int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s /qname\n", argv[0]);
return -1;
}
char* qname = argv[1];
int qflags = O_RDWR;
char msg[80];
pid_t pid = -1;
mqd_t qid = -1;
signal(SIGINT, sigHandler);
if ((pid = fork()) == 0)
{
/* child (ie. client) */
mqd_t qid = mq_open(qname, qflags);
if (qid == -1)
{
perror("Failed to open the message queue");
return -1;
}
do
{
printf("Client: ");
fgets(msg, sizeof(msg) - 1, stdin);
strip_newline(msg);
if (mq_send(qid, msg, strlen(msg), 0) == -1)
{
perror("Failed to send msg");
}
if (strlen(msg) > 0)
{
struct timespec ts = {time(0) + 5, 0}; // 5 seconds into the future
ssize_t rtn = mq_timedreceive(qid, msg, sizeof(msg), NULL, &ts);
if (rtn != -1)
{
msg[rtn] = '\0';
printf("%s\n", msg);
}
else
{
printf("Hmmm, I guess no one is home.\n");
}
}
} while (!quit);
}
else if (pid != -1)
{
/* parent (ie. server) */
mode_t qmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
struct mq_attr qattr;
qflags |= O_CREAT;
qattr.mq_flags = 0;
qattr.mq_maxmsg = 10;
qattr.mq_msgsize = sizeof(msg);
qattr.mq_curmsgs = 0;
mqd_t qid = mq_open(qname, qflags, qmode, &qattr);
if (qid == -1)
{
perror("Cannot open message queue");
return -1;
}
do
{
ssize_t rtn = mq_receive(qid, msg, sizeof(msg), NULL);
if (rtn != -1)
{
msg[rtn] = '\0';
if (strcasecmp(msg, "knock knock") == 0)
{
strcpy(msg, "Server: Who's there?");
if (mq_send(qid, msg, strlen(msg), 0) == -1)
{
perror("Failed to send response message");
}
}
}
else
{
perror("Failed to receive message");
}
} while (!quit);
}
else
{
perror("Cannot fork child");
return -1;
}
mq_close(qid);
mq_unlink(qname);
return 0;
}
void strip_newline(char* str)
{
char* nl = strchr(str, '\n');
if (nl)
{
*nl = '\0';
}
}
void sigHandler(int sig)
{
quit = true;
}
P.S. Normally I would not combine the client and server code into one source file. I would normally implement these in separate files, and create two executables.