Problem Running Message Queue on two terminals - c

I am trying to run two processes which are basically sending and receiving messages using message queue(SYS V). While I can run two process on same terminal tab by keeping my receiver in background
./receiver &
and sender in the foreground.
./sender
which is working fine but causing all my prints from sender & receiver display on same tab.
If I try to run receiver on one terminal tab and sender on other terminal-tab, the processes are not working correctly, they fail to identify message queue exist on the system.
I am not sure if its the terminal issue, or my program issue, I am using MobaXterm terminal.
Added code below, Am I missing w.r.t running processes on two different terminals I would like to know.
receiver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define PATH "/tmp/CMN_KEY"
struct message_text {
int qid;
char buf [200];
};
struct message {
long message_type;
struct message_text message_text;
};
int main (int argc, char **argv)
{
key_t key;
int qid;
struct message message;
if ((key = ftok (PATH,'Z')) == -1) {
printf ("ftok");
exit (1);
}
if ((qid = msgget (key, IPC_CREAT | 0660)) == -1) {
printf ("msgget");
exit (1);
}
printf ("Receiver: Waiting for MSG!\n");
while (1) {
// read an incoming message
if (msgrcv (qid, &message, sizeof (struct message_text), 0, 0) == -1) {
printf ("msgrcv");
exit (1);
}
printf ("Receiver: MSG Received.\n");
// message from sender
int length = strlen (message.message_text.buf);
char buf [20];
sprintf (buf, " %d", length);
strcat (message.message_text.buf, buf);
int client_qid = message.message_text.qid;
message.message_text.qid = qid;
// send reply message to Sender
if (msgsnd (client_qid, &message, sizeof (struct message_text), 0) == -1) {
printf ("msgget");
exit (1);
}
printf ("Receiver: Response sent to Sender .\n");
}
}
sender.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define PATH "/tmp/CMN_KEY"
struct message_text {
int qid;
char buf [200];
};
struct message {
long message_type;
struct message_text message_text;
};
int main (int argc, char **argv)
{
key_t key;
int sender_qid, myqid;
struct message my_message, return_message;
// queue for receiving messages from receiver
if ((myqid = msgget (IPC_PRIVATE, 0660)) == -1) {
printf ("msgget: myqid");
exit (1);
}
printf("Sender created q with ID: %d\n" , myqid);
if ((key = ftok (PATH,'Z')) == -1) {
printf ("ftok");
exit (1);
}
if ((sender_qid = msgget (key, 0)) == -1) {
printf ("msgget: sender_qid");
exit (1);
}
my_message.message_type = 1;
my_message.message_text.qid = myqid;
printf ("Input a message: ");
while (fgets (my_message.message_text.buf, 198, stdin)) {
int length = strlen (my_message.message_text.buf);
if (my_message.message_text.buf [length - 1] == '\n')
my_message.message_text.buf [length - 1] = '\0';
// send message to Receiver
if (msgsnd (sender_qid, &my_message, sizeof (struct message_text), 0) == -1) {
printf ("client: msgsnd");
exit (1);
}
// read response from Receiver
if (msgrcv (myqid, &return_message, sizeof (struct message_text), 0, 0) == -1) {
printf ("client: msgrcv");
exit (1);
}
// Return message from Receiver
printf ("Return Message From Receiver: %s\n\n", return_message.message_text.buf);
printf ("type a one more message: ");
}
// remove message queue
if (msgctl (myqid, IPC_RMID, NULL) == -1) {
printf ("client: msgctl");
exit (1);
}
return
}

Related

C recv function doesnt work all the time, it sometimes doesnt read and store all incoming data

We are working on a project where we want to communicate with a server.
This is our function to communicate with the server, but somehow it does not read the incoming messages correctly all the time.
Sometimes in the buffer there is something like:
(Server sends)"+ Client version acClient: ID 38ail6ii3s8jc"
instead of:
(Server sends)"+ Client version accepted - please send Game-ID to join"
(We send)"Client: ID 38ail6ii3s8jc"
So, I think the error is within the char *receiveAnswer(int sock) function.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#define BUFFERSIZE 1024
#define bzeroNew(b,len) (memset((b), '\0', (len)), (void) 0) //buffer loeschen
#define VERSION "VERSION 3.4\n"
#include "functions.h"
char buffer[BUFFERSIZE];
int prologEnd = 0;
int proof;
//liest von Server eine Nachricht ein und speichert sie im buffer ab
char *receiveAnswer(int sock) {
bzeroNew(buffer, BUFFERSIZE);
if(recv(sock, buffer, sizeof(buffer), 0) < 0) {
perror("ERROR: Empfangen fehlgeschlagen\n");
}
printf("%s", buffer);
return buffer;
}
void sendResponse(int sock, char* message) {
bzeroNew(buffer, BUFFERSIZE);
strcpy(buffer, message);
proof = send(sock, buffer, strlen(buffer), 0);
if(proof < 0) {
perror("ERROR: Senden fehlgeschlagen\n");
}
printf("Client: %s\n", buffer);
receiveAnswer(sock);
}
int performConnection(int sock, char* gameID) {
bzeroNew(buffer, BUFFERSIZE);
receiveAnswer(sock);
while(strncmp(buffer, "+", 1) == 0 && prologEnd == 0) {
if(strncmp(buffer, "+ MNM Gameserver", 16) == 0) {
receiveAnswer(sock);
sendResponse(sock, VERSION);
}
else if(strncmp(buffer, "+ Client", 8) == 0) {
sendResponse(sock, gameID);
}
else if(strncmp(buffer, "+ PLAYING", 9) == 0) {
sendResponse(sock, "PLAYER\n");
receiveAnswer(sock);
}
else if(strncmp(buffer, "+ YOU", 5) == 0) {
receiveAnswer(sock);
printf("\n");
prologEnd = 1;
}
else if(strncmp(buffer, "+ TOTAL", 7) == 0) {
receiveAnswer(sock);
receiveAnswer(sock);
prologEnd = 1;
}
}
bzeroNew(buffer, BUFFERSIZE);
return 0;
}
This is our main() function, but I think the error is within the file above:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h> // für Warten auf Kindprozess
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
// für Shared Memory:
#include <sys/ipc.h>
#include <sys/shm.h>
#include "functions.h"
#include "sharedMemory.h"
// dublicat, brauchen wir das?
#define GAMEKINDNAME "NMMorris"
#define HOSTNAME "sysprak.priv.lab.nm.ifi.lmu.de"
#define PORTNUMBER 1357
int main (int argc, char *argv[]) {
char gamekindname[256] = "NMMorris";
char hostname[256] = "sysprak.priv.lab.nm.ifi.lmu.de";
int portnumber = 1357;
char* gameID = argv[2];
char playerNumber[256];
char configFile[256] = "client.conf" ;
int fd[2]; // TODO: fd und client_fd vereinen
//gameID formatieren
char bufferGameID[64];
strcpy(bufferGameID, "ID ");
strcat(bufferGameID, gameID);
strcpy(gameID, bufferGameID);
strcat(gameID, "\n");
int i;
char tmp[256];
//Argumente einlesen und an Variablen übergeben
for(i = 3; i < 7; i++) {
strcpy(tmp, argv[i]);
if (strcmp(tmp, "-p") == 0){
strcpy(playerNumber, argv[i+1]);
} else if (strcmp(tmp, "-conf") == 0){
strcpy(configFile, argv[i+1]);
}
}
config configMain = readConfig(configFile);
strcpy(gamekindname, configMain.gameKind);
strcpy(hostname, configMain.hostServerName);
portnumber = configMain.portNmbr;
printf("\n>>>Config File Data<<<\n");
printf("HostServerName: %s\n", hostname);
printf("PortNumber: %d\n", portnumber);
printf("GameKind: %s\n\n ", gamekindname);
//From here: sockets
int sock, client_fd;
struct sockaddr_in serv_addr;
struct hostent *server;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("\nERROR: Socket creation error \n");
return - 1;
}
//ipAdresse nachschauen
server = gethostbyname(hostname);
if (server == NULL)
{
perror("ERROR: no such host\n");
}
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portnumber);
memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
if ((client_fd = connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))) < 0) {
perror("ERROR: Connection Failed \n");
return -1;
}
printf(">>> Mit Host : %s verbunden <<<\n", hostname);
if(performConnection(sock, gameID) != 0) {
perror("performConnection Failed\n");
} // TODO: verlagern
close(client_fd);
return 0;
// Shared Memory Segment erstellen
int shmid_game = shmget(KEY, sizeof(gameInfo), IPC_CREAT | SHM_R | SHM_W);
if (shmid_game == -1) {
perror("Error while creating shared memory segment");
exit(EXIT_FAILURE);
} else {
printf("Creation successful\n");
}
int shmid_player = shmget(KEY, sizeof(playerInfo), IPC_CREAT | SHM_R | SHM_W);
if (shmid_player == -1) {
perror("Error while creating shared memory segment");
exit(EXIT_FAILURE);
} else {
printf("Creation successful\n");
}
// Prozess mit SHM verbinden
void* shm_game = shmat(shmid_game, 0, 0);
if (shm_game == NULL) {
perror("Error while attaching shared memory segment");
exit(EXIT_FAILURE);
} else {
printf("Attachment successful\n");
}
void* shm_player = shmat(shmid_player, 0, 0);
if (shm_player == NULL) {
perror("Error while attaching shared memory segment");
exit(EXIT_FAILURE);
} else {
printf("Attachment successful\n");
}
// Kindprozess (Connector) erstellen
pid_t pid;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fehler bei Erstellung des Kindprozesses.\n");
} else if (pid == 0) { // Kindprozess (Connector)
close(fd[1]);
performConnection(sock, gameID);
} else { // Elternprozess (Thinker)
close(fd[0]);
}
return 0;
}
TCP is a stream-oriented protocol, not a message-oriented one. A message sent as 100 bytes can be received as 1 100-byte read or as 100 1-byte reads, or any combination in between. This means that you must keep looping on the recv() until you have the whole message. That, in turn, means you need to know when a message is completely received. Either prepend the message's length before the message, use a fixed-size message, or have a unique recognizable terminator at the end of the message.
recv() returns the number of bytes that it has written into your buffer -- which is to say, it returns the number of bytes that it currently has available to give to you at the time you called it. Importantly, that will often be less than the number of bytes you requested, so it is mandatory that you check the return value of recv() to find out how many bytes you actually received, and not just assume that the value returned by recv() is equal to sizeof(buffer).
OTOH if you want recv() to not return until sizeof(buffer) bytes have been successfully read, you can pass the MSG_WAITALL flag to recv() in the fourth argument.
From the recv man page:
This flag requests that the operation block until the full
request is satisfied. However, the call may still return
less data than requested if a signal is caught, an error
or disconnect occurs, or the next data to be received is
of a different type than that returned. This flag has no
effect for datagram sockets.
It is not guaranteed that recv() will get all of the bytes sent at once. The convention is to call it in a loop until you've read all the bytes.
NB that recv() returns 0 when the client is stalling or closed the connection, and -1 on a read error.
Handling partial send()s:
int sendall(int s, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while(total < *len) {
n = send(s, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
— From Beej's guide to Network Programming
The above code snippet calls send() in a loop until all the data has been sent.
You can now write a similar recv_all function that calls recv() in a loop until it has read all the data.
Handling partial recv()s:
Perhaps something like this:
/* Synopsis: Calls recv() in a loop to ensure
* len bytes have been read. Stores
* the total number of bytes sent in len.
*
* Returns: 0 on failure, 1 otherwise.
*/
static int recv_all(int sockfd, char *buf, size_t *len)
{
size_t bytes_left = *len;
size_t total = 0;
ssize_t rv = 0;
errno = 0;
while (total < *len) {
rv = recv(sockfd, buf + total, bytes_left, 0);
if (rv == 0) { /* Client closed the connection or is stalling */
return 0;
} else if (rv == -1) { /* A read error */
perror("recv");
return 0;
}
total += rv;
bytes_left -= rv;
}
*len = total;
return 1;
}
recv() may also return 0 when 0 characters were read. In that case, len can be compared against the original len to see if the call to recv() was successful.
Note: The above recv_all function has not been tested, and hence is not guaranteed to be bug free. It's meant to be an example.

sending array with message queue

i have been trying to send an array with message queues in c. It works with a normal string, but I don´t know how to do it with an array. this is my code so far with the string attempt. Do I need to seperate the writer and receiver? I also need to send the array two more times, but I can´t start before it sends the first time.
thanks for any help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/msg.h>
#define maxArr 100
//create buffer
struct msgbuffer{
long msgtype;
char msgtext [100];
int arr[maxArr];
}msg;
int main(int argc , char ** argv){
//needed variables
int returncode_msgget;
int returncode_msgrcv;
int i;
//create message queue
returncode_msgget = msgget(1234, IPC_CREAT |0600);
//generating random numbers
srand(time(NULL));
for (i = 0; i < 10; i++) {
msg.arr[i] = rand() %101;
printf("%d,", msg.arr[i]);
}
//sending message
msg.msgtype = 1;
strcpy(msg.msgtext,"test");
//checking if message was sent
if (msgsnd(returncode_msgget, &msg, sizeof(msg.msgtext), 0) == -1){
printf("message not sent\n");
perror("msgsnd()");
}
//buffer for message receiver
wait(NULL);
struct msgbuffer{
long mtype;
char mtext [100];
} msg;
// reaching message queue
//checking if message queue is reachable
msg.mtype = 1;
if ((returncode_msgget = msgget(1234, IPC_CREAT| 0600)) < 0) {
printf("could not reach Message queue\n");
perror("msgget()");
}
//checking if message was received
returncode_msgrcv = msgrcv(returncode_msgget, &msg, sizeof(msg.mtext), msg.mtype, MSG_NOERROR|IPC_NOWAIT);
if (returncode_msgrcv == -1) {
printf("message not received\n");
perror("msgrcv()");
//if message received, notification
}else {
printf ("Diese Nachricht wurde aus der Warteschlange gelesen : %s \n" , msg . mtext );
printf ("Die empfangene Nachricht ist %i Zeichen lang .\n" , returncode_msgrcv );
}
printf("test");
}
this was my attempt for sending an array which I saw on another post here:
//checking if message was sent
if (msgsnd(returncode_msgget, (int*) &msg.arr[i], sizeof(msg.arr[i]), 0) == -1){
printf("message not sent\n");
perror("msgsnd()");
}

C program not reading keyboard input

EDIT: the problem is that scanf (and other function I tried here) doesn't wait for the input, the program doesn't pause.
Using Ubuntu 18 on Virtual Box on Mac
I am writing a server/client using POSIX. I am not able to read keyboard input in client.c
char action_type[1];
printf("Chose action: T to request time, S to shut down\n");
scanf(" %c",action_type);
printf("%s", action_type);
if I put the same code as the first thing in main.c it works fine.
full code for server / client and commons is:
server
#include <stdio.h>
#include "mqueue.h"
#include "commons.h"
#include "errno.h"
#include "stdlib.h"
#include <string.h>
#include <time.h>
int status_closing = 0;
void send_time(char* clients_pid);
void send_activation(char* clients_pid);
//VARIABLES related to SERVERS QUEUE
mqd_t server; // server
struct mq_attr servers_attributes; // server creation attributes
struct mq_attr receiving_attributes; // server receiving attributes
// set up attributes
void set_servers_attributes(){
// set up server's attributes
servers_attributes.mq_maxmsg = QUEUE_SIZE;
servers_attributes.mq_msgsize = MESSAGE_SIZE;
printf("attributes set \n");
};
// open server
void open_servers_queue() {
server = mq_open (servers_path,
O_CREAT | O_RDWR | O_EXCL ,
0666, &servers_attributes);
if (server == -1) {
printf("failed to open server's queue\n");
printf(errno);
exit(-1);
} else {
printf("opened servers queue as: %d\n",server);
}
};
// check attributes
void check_attributes(){
if ((mq_getattr(server,&receiving_attributes)) == -1) {
printf("cannot read server's queue\n exit \n");
exit(-1);
}
};
void close_and_unlink_queue(){
printf("At exit closing and unlinking queue\n");
mq_close(server);
mq_unlink(servers_path);
};
int check_for_messages_in_the_queue(){
//printf("checking for messages\n");
int messages_in_queue;
messages_in_queue = receiving_attributes.mq_curmsgs;
//printf("there are %d message in the servers queue\n",messages_in_queue);
// printf("message in the queue!\n");
return messages_in_queue;
};
char* receive_message(){
char *receiving_buffer = malloc(sizeof(char)*MESSAGE_SIZE);
if ((mq_receive(server,receiving_buffer,MESSAGE_SIZE,NULL))>0){
return receiving_buffer;
}
else {
printf("Server failed to receive message");
mq_close(server);
mq_unlink(servers_path);
exit(-1);
}
};
void respond(char *message_type, char* clients_pid) {
printf("responding\n");
char* type_one = "1";
char* type_two = "2";
char *type_three ="3";
if (strcmp(message_type, type_one) == 0) {
printf("TYPE 1\n");
send_activation(clients_pid);
}
if (strcmp(message_type, type_two) == 0) {
printf("TYPE 2\n");
send_time(clients_pid);
}
if (strcmp(message_type, type_three) == 0) {
printf("type 3 - SHUTDOWN INITIATED\n");
}
}
void send_time(char* clients_pid) {
time_t mytime = time(NULL);
char *time_str = ctime(&mytime);
time_str[strlen(time_str)-1] = '\0';
char *clientpath[20];
int clients_pid_int = atoi(clients_pid);
sprintf(clientpath,"/%d",clients_pid_int);
printf("clients path: %s\n",clientpath);
mqd_t client;
client = mq_open(clientpath,O_RDWR , 0666, &servers_attributes);
if (client == -1) {
printf("failes opening client's queue \n");
exit(-1);
} else {
printf("connected to client's queue: %d\n",client);
}
};
void send_activation(char* clients_pid) {
char *clientpath[20];
int clients_pid_int = atoi(clients_pid);
sprintf(clientpath,"/%d",clients_pid_int);
printf("clients path: %s\n",clientpath);
mqd_t client;
client = mq_open(clientpath,O_RDWR , 0666, &servers_attributes);
if (client == -1) {
printf("failes opening client's queue \n");
exit(-1);
} else {
printf("connected to client's queue: %d\n",client);
char* activation = malloc(sizeof(char)*MESSAGE_SIZE);
char* activation_literal = "activation";
sprintf(activation,"%s",activation_literal);
int message_sent = mq_send(client,activation,MESSAGE_SIZE,0);
printf("message sent with: %d",message_sent);
}
};
int main() {
// clean remainings of previous trials
mq_close(server);
mq_unlink(servers_path);
// define atexit behaviour
atexit(close_and_unlink_queue);
//set servers attributes:
set_servers_attributes();
// open server's queue
open_servers_queue();
// receiving messages in the loop
int condition = 1;
while (1) {
check_attributes();
if (check_for_messages_in_the_queue() > 0) {
char *received_message = receive_message();
char *tok_one = strtok(received_message," ");
char *tok_two = strtok(NULL, " ");
//int clients_pid = atoi(tok_two);
respond(tok_one,tok_two);
} else if ((check_for_messages_in_the_queue() ==0) && (status_closing == 1)) {
printf("Server's queue is empty - work finished. closing down\n");
exit(0);
}
}
printf("Hello, World!\n");
return 0;
}
client
#include <stdio.h>
#include <mqueue.h>
#include <unistd.h>
#include "commons.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
mqd_t client;
mqd_t server;
char clientpath[20];
char* sending_buffer[MESSAGE_SIZE];
struct mq_attr clients_attributes;
struct mq_attr receiving_attributes;
void connect_to_server(){
server = mq_open(servers_path,O_WRONLY);
if(server == -1) {
printf("connection to server failed\n");
} else {
printf("connected to server with id: %d \n",server);
}
};
void set_clients_attributes(){
// deal with attributes
clients_attributes.mq_maxmsg = QUEUE_SIZE;
clients_attributes.mq_msgsize = MESSAGE_SIZE;
};
void create_clients_queue(){
// create clients path
pid_t client_pid = getpid();
sprintf(clientpath, "/%d", client_pid);
// open clients queue
client = mq_open(clientpath,O_RDONLY | O_CREAT | O_EXCL, 0666, &clients_attributes);
// printf(errno);
if (client == -1) {
printf("failes opening client's queue \n");
exit(-1);
} else {
printf("connected to client's queue: %d\n",client);
}
};
void register_at_server(){
message message;
message.mtype = 1;
int client_pid = getpid();
message.sender = client_pid;
char separator = ' ';
snprintf(sending_buffer,MESSAGE_SIZE,"%ld%c%d",message.mtype,separator,message.sender);
if ((mq_send(server,sending_buffer, MESSAGE_SIZE,0)) == -1) {
printf("failed to send registration request\n");
exit(-1);
}
else {
printf("%s",sending_buffer);
printf("sent registration request\n");
}
};
void close_and_unlink_queue(){
printf("At exit closing and unlinking queue\n");
mq_close(client);
mq_unlink(clientpath);
};
void check_attributes(){
if ((mq_getattr(client,&receiving_attributes)) == -1) {
printf("cannot read own's queue\n exit \n");
exit(-1);
}
};
int check_for_messages_in_the_queue(){
//printf("checking for messages\n");
int messages_in_queue;
messages_in_queue = receiving_attributes.mq_curmsgs;
//printf("there are %d message in the servers queue\n",messages_in_queue);
// printf("message in the queue!\n");
return messages_in_queue;
};
char* receive_message(){
char *receiving_buffer = malloc(sizeof(char)*MESSAGE_SIZE);
if ((mq_receive(client,receiving_buffer,MESSAGE_SIZE,NULL))>0){
return receiving_buffer;
}
else {
printf("Server failed to receive message");
mq_close(client);
mq_unlink(clientpath);
exit(-1);
}
};
void choose_action(){
char action_type[1];
printf("Chose action: T to request time, S to shut down\n");
scanf(" %c",action_type);
printf("%s", action_type);
};
int main() {
mq_close(client);
mq_unlink(clientpath);
connect_to_server();
set_clients_attributes();
create_clients_queue();
register_at_server();
int condition = 1;
int client_active = 0;
while (condition) {
check_attributes();
if (check_for_messages_in_the_queue() > 0) {
char *received_message = receive_message();
if ((strcmp(received_message, "activation")) == 0) {
client_active = 1;
condition = 0;
free(received_message);
}
}
}
char action_type[1];
printf("Chose action: T to request time, S to shut down\n");
scanf(" %c",action_type);
printf("%s", action_type);
printf("Hello, World!\n");
return 0;
}
commons
#ifndef SERVER_COMMONS_H
#define SERVER_COMMONS_H
#include <signal.h>
// define values of server queue attributes
//define message struct
typedef struct messgae {
char content[4096];
pid_t sender;
long mtype;
} message;
#define QUEUE_SIZE 10
#define MESSAGE_SIZE sizeof(message)
// define servers path
const char servers_path[] = "/server";
#endif //SERVER_COMMONS_H
``
this happens because the buffer is not empty and this function read from it.
to empty buffer just try this code:
while( getchar() != '\n');
it will empty the buffer and after it the functions will wait for input.
printf( "Enter a value :");
c = getchar( );
or
#include <stdio.h>
int main( ) {
char str[100];
int i;
printf( "Enter a value :");
scanf("%s %d", str, &i);
printf( "\nYou entered: %s %d ", str, i);
return 0;
}

System V Message Queues - getting message that already exists

I've been working on a project and one of the tasks that I have to do is passing the string received from another process through a pipe to yet another process but this time I have to use a message queue.
I've managed to learn how msgqueue works and made a simple working program but, the thing is, it works when receiving a string from stdin through fgets.
My question is:
Can I pass a string that is already saved in other variable (for example
char s[20] = "message test"; ) to the msgqueues mtext?
My simple program looks like that:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
struct msgbuf {
long mtype;
char string[20];
};
struct msgbuf mbuf;
int open_queue( key_t keyval ) {
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0660 )) == -1)
return(-1);
return(qid);
}
int send_message( int qid){
int result, size;
size = sizeof mbuf.string;
if((result = msgsnd( qid, &mbuf, size, 0)) == -1)
return(-1);
return(result);
}
int remove_queue( int qid ){
if( msgctl( qid, IPC_RMID, 0) == -1)
return(-1);
return(0);
}
int read_message( int qid, long type){
int result, size;
size = sizeof mbuf.string;
if((result = msgrcv( qid, &mbuf, size, type, 0)) == -1)
return(-1);
return(result);
}
int main(void){
int qid;
key_t msgkey;
msgkey = ftok(".", 'm');
if(( qid = open_queue( msgkey)) == -1) {
perror("openErr");
exit(1);
}
mbuf.mtype = 1;
fgets(mbuf.string, sizeof mbuf.string, stdin);
if((send_message( qid)) == -1) {
perror("sendErr");
exit(1);
}
mbuf.mtype = 1;
if((read_message(qid, mbuf.mtype))== -1){
perror("recERR");
exit(1);
}
printf("Queue: %s\n", mbuf.string);
remove_queue(qid);
return 0;
}
Your code uses fgets() to fill the buffer mbuf.string with input read from stdin. You can instead use something like strcpy(mbuf.string, "message test") where you can pass in a variable or use a hard coded string.
I recommend using the POSIX message queue API as the System V API is deprecated.

Error "Bad address" when reading from message queue on Linux

I have assignment when I need to write simple time server and a client using Linux message queue. The server opens a message queue and the client sends a request with his PID (message with type 1) and the server reads that message and sends a message with type of PID (taken from the message read). I put all the code below because I don't know where I made the mistake. I'm not Linux programming expert. Don't even know if I written server correct.
File that is included by server and client (I need to write it in this way).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#define QUEUE 100
#define PERM_ALL 0777
typedef struct my_msgbuf {
long mtype;
int pid;
} ClientMessage;
typedef struct my_msgbuf2 {
long mtype;
struct tm time;
} TimeMessage;
Server
int m_queue;
void cleanup(int signum) {
if (msgctl(m_queue, IPC_RMID, NULL) == -1) {
printf("Something happen on clean up\n");
exit(1);
}
exit(signum);
}
int main() {
ClientMessage pid_message;
TimeMessage t;
time_t clock;
struct tm *cur_time;
if ((m_queue = msgget(QUEUE, PERM_ALL | IPC_CREAT)) == -1) {
printf("Can't create and open message queue\n");
exit(1);
}
printf("created message queue = %d\n", m_queue);
fflush(stdout);
//t = malloc(sizeof(TimeMessage));
signal(SIGINT, cleanup);
while (1) {
if (msgrcv(m_queue, &pid_message, sizeof(pid_message.pid), 1, 0) == -1) {
break;
} else {
t.mtype = pid_message.pid;
clock = time(NULL);
cur_time = localtime(&clock);
memcpy(&t.time, cur_time, sizeof(struct tm));
msgsnd(m_queue, &t, sizeof(struct tm), 0);
}
}
cleanup(0);
}
Client
int main() {
int m_queue;
TimeMessage *t;
ClientMessage client;
if ((m_queue = msgget(QUEUE, PERM_ALL)) == -1) {
perror("Error in opening queue");
exit(1);
}
client.mtype = 1;
client.pid = getpid();
while (1) {
if (msgsnd(m_queue, &client, sizeof(client.pid), 0) == -1) {
perror("Error sending to queue");
exit(1);
} else {
if (msgrcv(m_queue, t, sizeof(struct tm), client.pid, 0) == -1) {
perror("Error reading from queue");
exit(1);
}
printf("time: %d:%d:%d\n", t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
}
}
return 0;
}
Both program compile without errors but client return "Error reading from queue" msgrcv is returning -1.
After adding the perror it appears that you have got the error stating "Bad Address" (EFAULT) which means that "The address pointed to by msgp (buffer) isn't accessible". From the code it appears that there has been no memory allocated to TimeMessage *t so you can either allocate memory or just change it to TimeMessage t and pass &t instead of t to msgrcv. Also size should be sizeof t (assuming the change from *t to t, or sizeof(TimeMessage) for *t) instead of sizeof(struct tm) (& obviously you would change printf statement accordingly)
Hope this helps!

Resources