[zeromq-dev] proper way to handle messages with c structures
Jens Auer
jens.auer at betaversion.net
Thu Jul 9 23:52:16 CEST 2015
Hi,
it is not recommended to use memcopied structs in C (or even worse classes in C++) as an exchanged format. There are many reasons why this can go wrong:
- You do not consider different byte-order
- The size of int,short etc. is not defined in C/C++. If you run the server on a 64-bit system, and the client on 32-bit system, you will run into problems
- The compiler is free to add padding between the struct members, e.g. to adhere alignment constraints
These are just the first things that come to my mind. The result is that an object of InitMsg can look very different in memory on two plattforms, even if both are running the same Linux version. Even on the same platform with identical operating systems, the layout could be different when client and server use different compiler options.
I would advise to use a serialization/deserialization framework to convert the structs into and from a well-defined representation. Google protocol buffers are often recommended, and I have seen C code using xdr (although I would never ever recommend this).
Best wishes,
Jens
Von: zeromq-dev-bounces at lists.zeromq.org [mailto:zeromq-dev-bounces at lists.zeromq.org] Im Auftrag von Andrew Simpson
Gesendet: Donnerstag, 9. Juli 2015 22:17
An: zeromq-dev at lists.zeromq.org
Betreff: [zeromq-dev] proper way to handle messages with c structures
I am modifying an existing application to use ZMQ to send/receive the data. The application is written in C on RHEL 6.6, using ZMQ 4.0.5. I am using router-dealer socket types. I do have the messages coming through right now, but I do not think I am doing this in the best possible way:
The application consists of a "server" and multiple "client" applications. These are separate binaries, not threads.
I am setting the ID on the Dealer socket for each client application. A message containing a C structure is passed from the client to the server.
An example C struct that I use:
struct InitMsg {
char myName[10];
int myUUID;
int someVar;
short someOtherVar;
};
The Client is the Dealer, server is the router socket.
METHOD 1:
Client sends the message:
zmq_send(serverSocket, &InitMsg, sizeof(InitMsg), 0);
On the server side, I do the following:
1. zmq_recv once to get the ID of the client
2. call a second zmq_recv to get the message from the client.
while the above seems to be working, It seems that I should be using something more like:
METHOD 2:
client:
zmq_msg_t newMsg;
zmq_msg_init (&newMsg);
zmq_msg_copy (&newMsg, &InitMsg);
zmq_msg_send (&newMsg, serverSocket, 0);
server:
zmq_msg_t *msg;
zmq_msg_init(&msg);
zmq_msg_recv(&msg, clientSocket, 0);
I'm looking for a recommendation about the best/most efficient way to handle sending/receiving c structures and I've gotten a little confused about everything :( There appears to be many ways to do this. I have no problem working directly with zmq objects/frames, etc... but if zmq_recv.zmq_send is just as efficient, I'm fine with it.
A few additional questions:
1. After reading the guide and examples, does the second method above handle getting the id, delimiter, and the message all in one?
2. Am I correct in that a router/dealer pattern, that the send is always: ID, delimiter, message?
Thanks for all your help.
Drew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20150709/97a6ffdb/attachment.htm>
More information about the zeromq-dev
mailing list