21

I'm looking for a way to get two programs to efficiently transmit a large amount of data to each other, which needs to work on Linux and Windows, in C++. The context here is a P2P network program that acts as a node on the network and runs continuously, and other applications (which could be games hence the need for a fast solution) will use this to communicate with other nodes in the network. If there's a better solution for this I would be interested.

Stephen Cross
  • 1,003
  • 1
  • 8
  • 19
  • 5
    I'm a little unsure about the question... are you asking about transferring data between two processes on the same host, or two processes that are (or could be) running on different hosts? – Jeremy Friesner Feb 07 '10 at 22:11
  • If you are looking for a better solution, what are you doing now? – ergosys Feb 07 '10 at 22:14
  • @Jeremy: Sorry, I wasn't clear enough. The two processes are on the same machine. – Stephen Cross Feb 07 '10 at 22:24
  • @ergosys: I was asking if anyone had better ideas than simply normal IPC...perhaps by passing sockets from one application to another so the application could send data down the socket directly (I don't know that this is possible...and it could be problematic if two apps wanted to communicate with the same node) – Stephen Cross Feb 07 '10 at 22:27

6 Answers6

17

boost::asio is a cross platform library handling asynchronous io over sockets. You can combine this with using for instance Google Protocol Buffers for your actual messages.

Boost also provides you with boost::interprocess for interprocess communication on the same machine, but asio lets you do your communication asynchronously and you can easily have the same handlers for both local and remote connections.

villintehaspam
  • 8,540
  • 6
  • 45
  • 76
  • Ok, looks like boost is the way to go with this...I'm already using it for boost::signal and I was probably going to use it for boost::asio – Stephen Cross Feb 07 '10 at 22:41
  • With Google Protocol Buffers, you can choose from [many available RPC implementations](http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns). – Grzegorz Wierzowiecki Aug 27 '11 at 18:36
5

I have been using ICE by ZeroC (www.zeroc.com), and it has been fantastic. Super easy to use, and it's not only cross platform, but has support for many languages as well (python, java, etc) and even an embedded version of the library.

AndiDog
  • 68,631
  • 21
  • 159
  • 205
rcv
  • 6,078
  • 9
  • 43
  • 63
3

Well, if we can assume the two processes are running on the same machine, then the fastest way for them to transfer large quantities of data back and forth is by keeping the data inside a shared memory region; with that setup, the data is never copied at all, since both processes can access it directly. (If you wanted to go even further, you could combine the two programs into one program, with each former 'process' now running as a thread inside the same process space instead. In that case they would be automatically sharing 100% of their memory with each other)

Of course, just having a shared memory area isn't sufficient in most cases: you would also need some sort of synchronization mechanism so that the processes can read and update the shared data safely, without tripping over each other. The way I would do that would be to create two double-ended queues in the shared memory region (one for each process to send with). Either use a lockless FIFO-queue class, or give each double-ended queue a semaphore/mutex that you can use to serialize pushing data items into the queue and popping data items out of the queue. (Note that the data items you'd be putting into the queues would only be pointers to the actual data buffers, not the data itself... otherwise you'd be back to copying large amounts of data around, which you want to avoid. It's a good idea to use shared_ptrs instead of plain C pointers, so that "old" data will be automatically freed when the receiving process is done using it). Once you have that, the only other thing you'd need is a way for process A to notify process B when it has just put an item into the queue for B to receive (and vice versa)... I typically do that by writing a byte into a pipe that the other process is select()-ing on, to cause the other process to wake up and check its queue, but there are other ways to do it as well.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
1

This is a hard problem.

The bottleneck is the internet, and that your clients might be on NAT.

If you are not talking internet, or if you explicitly don't have clients behind carrier grade evil NATs, you need to say.

Because it boils down to: use TCP. Suck it up.

Will
  • 73,905
  • 40
  • 169
  • 246
  • The two processes are on the same machine, but one of them is communicating with the internet. The other process must communicate with that one to send data on the P2P network. – Stephen Cross Feb 07 '10 at 22:32
  • aha, and I was thinking the question was about how to make a P2P network. I didn't even get started on hole-punching and relay servers and such. – Will Feb 08 '10 at 07:21
1

I would strongly suggest Protocol Buffers on top of TCP or UDP sockets.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • 2
    While UDP can be good in certain circumstances, TCP is the way to go if you want the data there in one piece and latency isn't the most critical component. – Xorlev Feb 07 '10 at 22:05
0

So, while the other answers cover part of the problem (socket libraries), they're not telling you about the NAT issue. Rather than have your users tinker with their routers, it's better to use some techniques that should get you through a vaguely sane router with no extra configuration. You need to use all of these to get the best compatibility.

First, ICE library here is a NAT traversal technique that works with STUN and/or TURN servers out in the network. You may have to provide some infrastructure for this to work, although there are some public STUN servers.

Second, use both UPnP and NAT-PMP. One library here, for example.

Third, use IPv6. Teredo, which is one way of running IPv6 over IPv4, often works when none of the above do, and who knows, your users may have working IPv6 by some other means. Very little code to implement this, and increasingly important. I find about half of Bittorrent data arrives over IPv6, for example.

Andrew McGregor
  • 31,730
  • 2
  • 29
  • 28