7
votes

I have a simple server written in C. It's main purpose is to communicate with some business partners over a proprietary protocol. For that reason and a few others, it must be written in C. I have a number of other processes, however, written in other languages (e.g. Python) that must communicate with the server (locally, on the same Linux server).

What are the best options for cross-language IPC in this scenario? Specifically, I think I have a handle on transport technologies: Unix domain sockets, named pipes, shared memory, ZeroMQ (Crossroads). I'm more interested in the best way to implement the protocol, in order to keep the C code small and maintainable, while still allowing communication from other languages.

Edit: there seems to be some confusion. I'm not interested in discussion of pros/cons of domain sockets, shared memory et. al. I am interested in msgpack (thanks unwind), and other technologies/approaches for implementing the wire protocol.

2
Wild guess, sockets if you want to transfer data serially, shared memory+shared semaphore if you want faster and more random ipc. - Shahbaz
OK, so what languages do you need, and what is required from the protocol? If it's just C & Python on Linux, you can trivially use fixed-size structures and be done with it. - Useless
Go is actually the primary other one, haskell is a nice to have. - brooks94

2 Answers

4
votes

It's hard to optimize (=select the "best") when the requirements are unknown. You do state that your goal is to keep the C code "small and maintainable", which seems to imply that you should look for a library. Perhaps msgpack over a local socket?

Also, your basic premise that the server must be written in C because you have a proprietary protocol seems ... weird, at least.

4
votes

Edit: What you need is a "serialization framework", i.e. something can turn a memory structure into a byte stream. The best candidates are:

Pros/cons:

Protocol Buffers

  • + Fast
  • + Easy to version (which you'll start to love very much when you need to make a change to your message format for the first time and which you will curse to hell before that)
  • - Solves many problems which you don't know about, yet. That makes the API a bit "strange". I assure you, there are very good reasons for what and how they do it but you will feel confused sometimes.

I don't know much about MessagePack.

Lastly:

JSON

  • + Any language out there can read and write JSON data.
  • + Human readable without tools
  • - somewhat slow
  • - the format is very flexible but if you need to make big changes, you need to find a strategy to figure out what format (= which fields) a message has when you read it.

As for the transport layer:

Pros/cons:

Shared memory

  • + Fastest option
  • - You need a second channel (like a semaphore) to tell the other process that the data is now ready
  • - gets really ugly when you try to connect more then two processes
  • - OS specific

Named pipes

  • + Very easy to set up
  • + Fairly fast
  • - Only allows two processes to talk ... or rather one process to talk to another in a single direction. If you need bi-directional communication, you need several pipes

Sockets

  • + Pretty easy to set up
  • + Available for all and any languages
  • + Allows remote access (not all processes need to be on the same machine)
  • + Two-way communication with one server and several processes
  • - Slower than shmem and pipes

ZeroMQ

  • + Like sockets but better
  • + Modern API (not that old IPC/socket junk)
  • + Support for many languages...
  • - ...but not all

If you can I'd suggest to try ZeroMQ because it's a modern framework that solves many of the problems that you'll encounter with the older technologies.

If that fails, I'd try sockets next. They are easy, well supported and docile.