Message Queue - Multiple processes send cmd on a msgqueue - c

I have a scenario where multiple processes (p1,p2,etc) simultaneously send a command (post) to a msg Queue(cmd_msg_q).
And there is one receiver processes (R1) which retrieves the msg from the queue and send appropriate reply back to the processes on another msg queue ( response_msg_q ).
how to reply from the receiver process so that the message is sent to that particular processes ?
( Using Posix Message queue. ) Here Process A, B or C gets created dynamically. Max limit is 20 process which can send commands.

In that case you'll have to integrate some ID of the sender in the message. Also note that these queues are essentially one-way, so to send messages back you need to create a queue on which the initial receiver will send, and the initial sender will listen for replies.
This is harder to explain than I initially thought, so let's try with and example. Assume we have programs A B and C where A and B send to C. They do so via the same queue. C will know who sent the message because the sender's identification is embedded in the message, and will post the reply to either the queue read by B or the queue read by C.

POSIX message queues pretty much require that you establish a second queue for each process and there is a pretty well establish pattern for this.
Your cmd_msg_q should be an established, well known queue (i.e. the path name). The system can create the queue (e.g. a startup script) before any applications are launched or the receiving process can create it before any sender processes are launched.
Establish a protocol of message types, minimally: (1) open output queue; (2) process message; (3) close output queue. Each message will need to contain an indication of which sender process is submitting the transaction e.g. pid or some unique identifier.
The sender processes create their own queues (e.g. input to them and output to the receiving "command" process. They send an "open queue" message to the receiver along with the path name of the queue they just created. The command process opens the output queue(s) to the receivers and acks that communication is established.
"process" message types are exchanged. The command process reads input from the combined source queue, and replies to appropriate output queue based on the identifier in each message.
Client (receiver) queues send a "close queue" message type when they are done. Command process sends an ack and closes that receiver queue. Client processes the ack and closes it queue.

Related

Is it possible to send signals through IPC Message Passing Queue?

I have tried calling kill from process A to process B and the process B has successful reacted to the signal. The problem is I don't want to send signals from the kill function directly for two reasons:
1) Sometimes the process A may not have the permissions, ex. process B is ran by another user
2) I want to be able to send signals from A to B through the message queue
I am creating a message queue from which I send "objects" of the following structure
typedef struct msg {
long message_type;
char message_text[SIZE];
}message;
I want to know if it is possible for process A to signal B through IPC Message Passing. I know I can achieve this by sending the signal type into the message_text from process A to B and then inside the process B check the type of the signal and act properly but I was wondering if there is another way.
Would this be possible by passing sigaction objects as messages:
struct sigaction as;
//...
msgsnd(queue_id, &as, length, IPC_NOWAIT);
//...
I know this is completely infeasible but this is what I am trying to achieve. Thank you
Based upon your comments it seems that you want B to be able to receive messages but when it receives a "signal" message it needs to act like it received a regular signal. You mentioned that the B needed to react to SIGTERM or SIGINT from the "signal" message.
The way to achieve this is depends upon using POSIX message queues or System V message queues.
Either way it doesn't seem that you want to use polling of the message queue by the main thread of B as that would add to much latency to responding to the "signal" message.
So with POSIX message queues you can use mq_notify() to run either a thread or raise a signal that a new message has arrived. Otherwise B can use a thread (or even fork()) to poll the message queue.
After a "signal" message is received you have a couple of options. A) You can use either kill or raise in B to send a signal of the correct type to itself (or parent in case of fork), or B) just call a function that does what you want (that sort of thing).
Process A can send a "signal" message whenever it wants. But you need to understand that if you are using named queues they are persistent. That is that A can send a "signal" message before B even starts, and then when B starts that message is waiting there. Depending on how the message queue is made it can be N messages deep and have older messages in the queue. One way to deal with that is for B to empty the queue before processing any of the messages.
Message queues can’t achieve how signals do. With signal it is possible to asynchronously interrupt or kill process but with message queue when receiving process checks message or wait on it and exits after receiving message, it actually will ignore that message rest of path of execution(synchronous). But, It is possible to achieve with threads.
If you were using a POSIX message queues (using mq_send/mq_receive), then process B can request (with mq_notify) to be sent a signal every time a message is sent to the message queue. However, your example seems to be using a SYSV legacy message queue (msgsnd) which does not suppport any kind of notify.

Sending same data to two different thread using message queue (single message queue) in C

Is to possible to send the same data from sender thread to two different receiver threads using message Queue mechanism. Receiver thread should receive same data. As per my understanding Shared memory with synchronization mechanism is proper solution for such scenario. But I was wondering if we could do it using message queue as if one thread pop the data other thread won't have anything to receive from the system message queue.

Multiple messages in message queue

This is probably a really dumb question, but googling isn't working out so here goes. I am writing a program using message queues to send a range of values to different processes. I have done research that indicates that I use msgsnd() to store a message on the queue and msgrcv() to receive messages. I need to store a start number and an end number in the queue. So my question is can I store multiple messages in this queue and if so, how to I go about storing them and retrieving them? TIA for all your help.
The concept of a queue means you can put things in (msgsnd) which creates one message in the queue. To receive one message, you have to call msgrcv. Each receive will normally only return one message, so if you send n messages, you have to receive n messages.
Queues are generally seen as FIFO (first in, first out), so the message creates by the first msgsnd will be the first message returned by msgrcv.
This is a little weakend if you message queues that operate over the network (and/or in a cluster). Due to network latency/failover/retries etc messages can get out of order, so it's generally advised to build the messages with all necessary information in them to process correctly for those cases.

Is there a way to send EOF to the process reading a message queue?

I have one process sending data through a message queue with msgsnd. Another process reading from the queue with msgrcv. The reading process needs to wait until it has all messages before it can continue. How can I tell it that all messages have been sent?
The way I've been doing it is after the sender has sent all its messages it then checks the number of messages in the queue in a while loop. When there are no more messages it closes the queue.
That tells the reading process to continue doing other things. This doesn't seem very reliable though. Many time the sending process will get stuck in an infinite loop of checking the queue status.
Is there a way for me to just send an EOF message and have the reading process watch for that? Then I could just send EOF and have the sending process exit.
Normally the receiver notices that the sender has finished sending because it tries to receive the next message and the receive call indicates that there was nothing left to receive. With communication through file descriptors (pipes, sockets), closing the is how you “send EOF”, and the read call returns 0 bytes. With message queues, it's a little different, because they are message-based rather than streams and there are often multiple senders.
You can call msgctl with the command IPC_RMID. This causes any waiting or subsequent call to msgrcv (or msgsnd) to return -EIDRM (-EINVAL on some BSD systems). The problem with this approach is that there may be messages pending in the queue that the receiver has not read yet and will thus we lost.
Instead, when the sender has nothing else to, have it send a message onto the queue that says “I'm finished”. In the receiver, when you receive this message, remove the queue. This works well when you use the queue between threads of one process. If there are multiple processes, the sender could die without having send the termination message.
How to handle the multi-process case will depend on the structure of your application, and in particular what the reading process wants to do when the sender is dead. One way you can detect this is by having a pipe between the sender and the receiver. Have a thread on the receiver listen on that pipe; if it detects the end of the file, it can
set a variable that is shared with the thread that calls msgrcv;
peek at the queue (msgctl with IPC_STAT);
if the queue is empty (msg_qnum == 0), remove it.

TCP server sending and receiving data multiple clients with multithreading

I want to design a TCP server which listens for x clients. X is small, say around 10 and its fixed. Clients may connect at any time. Once the connection is established (accept() successful) I spawn a thread for each client and handle them.
In this handle() function I want to send commands to client and receive the data accordingly.
Problem:
Once a command has been sent from the server the client responds by sending data continuously. How do I send a command back to the client to stop it? As with the current code I'm in a loop receiving data from the client.
I don't know how to send the command from server thread while receive is in progress, like should I need to have another thread (to send cmds) once the connection is established?
How to continuously receive data from clients and also send commands at the same time? Sending commands to each client based on user inputs. (Say user wants client1 to start sending data, then I have to send START to client1. And user wants to stop the client1 from sending, so I need to send STOP to client1 And if user wants data3 cmd to be sent to client 4 then send command DATA3 to client4 etc. How do identify the client in this case? Basically forming a small protocol**
The below code is working where I can listen on socket and client connects and sends data. I'm not sure of how to send user inputted commands to the right client (say client4) and also receive at same time.
If you want to really continously stream data and in parallel want to exchange commands you won't get around an addtional connection to establish the command channel. The alternativ would be some kind of multiplexing. Stream a chunk of data, check for commands, stream the next chunk, check for commands again ... - complicated and error prone as the stream is continously interupted ...
The stone old ftp protocol does something similar: http://en.wikipedia.org/wiki/Ftp and https://www.rfc-editor.org/rfc/rfc959 (see ascii art in chapter 2.3)
Presuming you want to have another thread initiate the request to send a command, you can accomplish what you want using standard asynchronous i/o, adding in another channel - a pipe - to receive commands from the other thread. Pseudocode:
Master thread:
while(1) {
newsocket = accept(listen socket)
pipefds = pipe()
new thread(Receiver, newsocket, pipefds.read)
}
Receiver thread:
while(1) {
readfds = [ pipefds.read, newsocket ]
poll( readfds ) // wait for there to be data on one of the fds
if (data ready on newsocket) {
read (newsocket)
process data
}
if (data ready on pipefds.read) {
read (pipefds.read)
send command
}
}
Commander thread:
write (pipefds.write, command)
The select in the main Receiver loop will wake up whenever there is data to read on the socket, OR if another thread has sent a command that needs to be sent to the remote connection.
Key syscalls to look up info on are poll (or select), and pipe.
WOO HOO! You've decided to dive into a pretty hairy subject, my friend.
Let me first rephrase your problem: your program can only wait for one thing at a time. If it's waiting on receive, it can't be waiting on send. So you just can't send and receive at the same time.
This is solved by multiplexing: waiting on multiple things.
Googling keywords: io, multiplexing, select, poll.
SO related question: read and write to same socket (TCP) using select
Another approach is to enter a nonblocking-read -> nonblocking-write -> sleep loop. This is obviously less than optimal, but may be enough for your case.
I've had some fun in the past designing my own bi-directional protocol for low level devices that can't communicate at the same time. One method you can use is mutual yielding: establish a mechanism for passing messages to and from the client and server. Stream any commands or messages you need to send, then yield the stream to the other side. The other side will then stream any messages or commands, then yield the stream to the original side. The only problem with this mechanism is that it's very laggy with high-ping connections, such as international internet connections.
This has been mentioned already, but I might as well rehash it. Computers have multiplexing built in to their networking hardware already, so you can do "concurrent" send/recv calls. Just run a pair of threads for each connection: a recv thread and a send thread. This should be the most robust solution.

Resources