venkysmarty
venkysmarty

Reputation: 11431

Passing messages between processes using message queues

I have a requirment to have communication between two processes using message queues. One process sends the request to another process and other process sends response.

For example one of the request is list all the filenames opened by the process. I have made interface structure as

 #define LIST_NAMES   1
 #define LIST_FILE_NAMES_RESP  2

 struct sFileStruct {
  unsigned int  uiCommand;
  unsigned long ulNoOfBytes; // Number of bytes to be parsed in cha* pointer below
  char*         pRecvData;   // file names packed here in response.
 };


 sFileStruct inData;
 // I am filling the data.
 int inSize = sizeof(inData);

 mq_send(m_qSendDesc, (char*)&inData, inSize, inPriority);

I think problem with above design is that as file names legth is changing char* pointer pointing to data is different, but size of structure is always constant, so receiver is not receving all the data and receiver is crashing while accessing the char* pointer.

I want to sent full data in one mq_send, and don't want to have static array inside structure. Is there any other way using message queues we can achieve this.

Please provide your inputs. Thanks

Upvotes: 1

Views: 4626

Answers (3)

Dmitry Yudakov
Dmitry Yudakov

Reputation: 15734

You could make a wrapper over mq_send() having char buffer allocated.

Every message you send will be serialized into this buffer and then you will pass it to mq_send with appropriate length - sizeof(int) + sizeof(long) + strlen(pRecvData).

The receiver will read this data and deserialize it into sFileStruct.

IMHO using std::string instead of char* would be better.

Sample code (not tested):

class MQWrapper
{
    std::string m_strBuffer;
public:
    int Send( const sFileStruct& sfs )
    {
        m_strBuffer.clear();
        m_strBuffer.append( static_cast<const char*> & sfs.uiCommand, sizeof(sfs.uiCommand) );
        m_strBuffer.append( static_cast<const char*> & sfs.ulNoOfBytes, sizeof(sfs.ulNoOfBytes) );
        m_strBuffer.append( sfs.pRecvData ); // only if it's zero-terminated string!!!

        return mq_send(m_qSendDesc, m_strBuffer.c_str(), m_strBuffer.length(), inPriority);
    }


    char m_receiveBUffer[ BUFFER_SIZE ];

    int Receive( sFileStruct& sfs )
    {
        int res = mq_receive( m_qSendDesc, receiveBUffer, BUFFER, outPriority );
        if( res < 0 )
            return res;
        if( res < sizeof(int) + sizeof(long) )
            return -1000; // malformed message
        sfs.uiCommand = * ( static_cast<unsigned int*> (m_receiveBUffer[0]) );
        sfs.ulNoOfBytes = * ( static_cast<long*> (m_receiveBUffer[ sizeof(int) ] ) );

        // I don't really use this style in my work and not sure how to use it
        // str::string would be much easier
        int stringLen = res - sizeof(int) - sizeof(long);
        sfs.pRecvData = new char [ stringLen + 1 ]; // you have to delete [] it later
        if( stringLen > 0 )
            strcpy( sfs.pRecvData, receiveBUffer + sizeof(int) + sizeof(long), stringLen );
        ss.pRecvData[ stringLen ] = '\0'; // null terminator
        return 0;
    }
};

Upvotes: 1

Simon Courtenage
Simon Courtenage

Reputation: 416

Shouldn't mq_send's second parameter be a const char* value? But you're passing a custom-written struct. I would write some code to serialize or turn the struct, if I were you, into a const char*, then use strlen to get its length and pass those two values as the second and third arguments to mq_send.

Upvotes: 0

Numenor
Numenor

Reputation: 1706

Receiver is crashing because it can not access your pointer which is only available for usage from sender program. You need to send the actual data to the message queue not a pointer.

Upvotes: 3

Related Questions