13

Currently I am working on a multi-process desktop application on Windows. This application will be a shrink wrapped application which will be deployed on client machines across the world. While we can have broad specifications for the machines - e.g. Windows XP SP3 with .Net 4.0 CF, we wont have control over them and we cant be too specific on their configuration - e.g. we cannot specify the machine must have a cuda 1.4 capable graphic processor etc.

Some of these processes are managed (.Net 4.0) and others are unmanaged (C++ Win32). The processes need to share data. The options I have evaluated to date are

  • Tcp sockets
  • Named Pipes

Pipes seem to perform a little better, but for our needs - performance from both are acceptable. And sockets give us the flexibility of crossing machine (and operating systems - we would like to support non-Microsoft OSes eventually) boundaries in the future hence our preference for going with sockets.

However - my major concern is this - If we use Tcp sockets - are we likely to run into issues with firewalls? Has anyone else deployed desktop applications / programs that use TCP for IPC and experienced issues? If so - what kind?

I know this is a fairly open ended question and I will be glad to rephrase. But I would really like to know what kind of potential problems we are likely to run into.

edit: To throw a little more light - we are only transporting a few PODs, ints, floats and strings. We have built a layer of abstraction that offers 2 paradigms - a request/response and subscription . The transport layer has been abstracted away and currently we have two implementations - pipe based and TCP based.

6
  • To be clear, this is only on a single machine, so you're not using the named pipes to communicate between desktops? Or will there be some communication over the network as well? Commented Jun 4, 2012 at 20:59
  • For now - all the processes are running on a single machine. Eventually - way down the road - we will be running the processes on different machines.
    – quixver
    Commented Jun 4, 2012 at 21:04
  • You'll want to make sure you design for down the road :) Unless "way down the road" is theoretical ...
    – bryanmac
    Commented Jun 4, 2012 at 21:10
  • @bryanmac - agreed. That is why we are leaning toward sockets... unless of course supporting it in the wild is going to be a real headache.
    – quixver
    Commented Jun 4, 2012 at 21:15
  • 1
    Sorry for not updating - we ended up going with TCP/IP. Performance has been pretty good and we've used google protobufs on top (with both c++ and c#). And so far so good :]
    – quixver
    Commented Aug 6, 2012 at 18:00

3 Answers 3

9

Performance of pipes is often better on a fast LAN but TCP is often better on slower networks or WANs. See msdn points below.

TPC is also more configurable. Concerning firewalls, they allow you to open/close communication ports. If that's not an option or a concern, an alternative would be http (REST/json, web service, xml rpc, etc...) but you have to consider if the http overhead is acceptable. Make sure you try it with real world datasets (passing trivial data in a test makes the overhead seem unreasonable, which would be very reasonable with a real world data set).

Some other info from msdn:

In a fast local area network (LAN) environment, Transmission Control Protocol/Internet Protocol (TCP/IP) Sockets and Named Pipes clients are comparable in terms of performance. However, the performance difference between the TCP/IP Sockets and Named Pipes clients becomes apparent with slower networks, such as across wide area networks (WANs) or dial-up networks. This is because of the different ways the interprocess communication (IPC) mechanisms communicate between peers.

For named pipes, network communications are typically more interactive. A peer does not send data until another peer asks for it using a read command. A network read typically involves a series of peek named pipes messages before it begins to read the data. These can be very costly in a slow network and cause excessive network traffic, which in turn affects other network clients.

It is also important to clarify if you are talking about local pipes or network pipes. If the server application is running locally on the computer running an instance of Microsoft® SQL Server™ 2000, the local Named Pipes protocol is an option. Local named pipes runs in kernel mode and is extremely fast.

For TCP/IP Sockets, data transmissions are more streamlined and have less overhead. Data transmissions can also take advantage of TCP/IP Sockets performance enhancement mechanisms such as windowing, delayed acknowledgements, and so on, which can be very beneficial in a slow network. Depending on the type of applications, such performance differences can be significant.

TCP/IP Sockets also support a backlog queue, which can provide a limited smoothing effect compared to named pipes that may lead to pipe busy errors when you are attempting to connect to SQL Server.

> In general, sockets are preferred in a slow LAN, WAN, or dial-up network, whereas named pipes can be a better choice when network speed is not the issue, as it offers more functionality, ease of use, and configuration options.

For more information about TCP/IP, see the Microsoft Windows NT® documentation.

1
  • Thanks for pointing out the performance perspective Bryan! We had not really considered the network speed. Our performance testing to date has been mostly focused on running the different processes on the same machine. We have not really put in much testing effort for the distributed scenario.
    – quixver
    Commented Jun 4, 2012 at 21:02
3

If you need to impersonate the named pipe client's security credentials, there's really only one option :) And named pipes also have nicer names (although DNS SRV records can provide those for TCP ports also).

Otherwise, there's not much difference. Both treat the data as a stream of bytes, leaving you responsible for finding message boundaries yourself. Named pipes have an additional option of keeping message boundaries for you, but be warned, you must both create the pipe in message mode and explicitly set the read mode as well.

3
  • Not quite correct unless I misunderstand what you mean. Named pipes can be created in byte or message mode. In message mode, each WriteFile to the pipe becomes a separate message. Commented Jun 4, 2012 at 22:58
  • @Carey: I figured he was talking about pipes in byte mode, since it's being compared to TCP and not UDP. However, you are correct that message mode is available, so I added that to my answer.
    – Ben Voigt
    Commented Jun 4, 2012 at 23:56
  • @BenVoigt: I agree with you in the main point, but to be exactly you can send security token in Socket communication using SSPI (proprietary variant of GSSAPI). The code example are here. The code is tricky and too complex for the most practical usage, but it is still possible.
    – Oleg
    Commented Jun 5, 2012 at 11:29
1

If I correctly understand your requirements you need to communicate between processes running on the same computer. The processes probably run all in the same security context of the user which is logged on interactively.

In the case I should mention that there are different aspects of the solution. One problem is just to share the data between the applications. Another problem is the protocol which defines how the common data could be accessed and modified and how the communication between the processes take place. You can have for example one process which provide the data and all another subscribe the data. Another case: you can have common data which can be read or modified by all the applications and you need just be sure that nobody modify the shared data on the same time or nobody access the data during another modify it. Of cause it could be many other different communication scenarios.

Under the aspect I would suggest you two other options which you don't included in your question:

  • usage memory mapped files (see here and here)
  • usage of COM interface

Both ways can be good implemented in both .NET and unmanaged C++. The usage of memory mapped files is the best way from the performance point of view. If you create View which will be not associated with some physical file you will have just common memory which can be used between processes. You can use additionally an Mutex or Event to control that the memory will be not used at the same time by multiple applications.

In the most simple scenario you can even use #pragma data_seg in C++ to place some data in the named section of DLL and use /SECTION option (like /SECTION:.MYSEC,RWS) to make the data shared. You can use the DLL in all your .NET applications and in all unmanaged C++ application to access the common data. In the way you will have simple way to access to the common data.

If you need to have some more complex communication scenario the approach with COM interface in C++/.NET could be the best choice. In case of I would recommend you the article which describes step by step how to implement Primary Interop Assembly with the COM interface only in .NET and uses it in both .NET and C++ COM for the communication.

7
  • Hi Oleg, thanks for bringing up memory mapped files. However I don't think we will go down that route since both pipes and sockets (on the same machine) internally use memory mapped files - and we are ok with the overhead. We would prefer the flexibility pipes and sockets give us - since we can in future move the various processes to different machines. As for COM - unfortunately I am prejudiced against it ... too many years supporting applications using DCOM ;)
    – quixver
    Commented Jun 5, 2012 at 13:26
  • Oh - and we would also like to have the option of moving some of the applications (eventually) to non Microsoft platforms.
    – quixver
    Commented Jun 5, 2012 at 13:29
  • @quixver: It's not correctly to say that "both pipes and sockets (on the same machine) internally use memory mapped files". Sockets don't use memory mapped files at all and named pipes is much more complex as is could seems at the first look. If you just examine parameters of CreateNamedPipe you will see it. I just use the information which you wrote in your question. You wrote about "Windows XP SP3 with .Net 4.0 CF" and nothing about "non Microsoft platforms" and about "multi-process desktop application on Windows". If you need communication between different computers you should write it
    – Oleg
    Commented Jun 5, 2012 at 14:04
  • @quixver: You should know more as me what requirements you really has. If you encapsulate the access to the shared memory in one module it will be not important which requirements you will need later. You can just implement in the best way your current requirements and update the module later when it will be needed. About COM I wrote that all depend on the communication protocol which you need to implement. Additionally the complexity of data could be important. If you have for example data in for of link-list it will be complex to serialize the data, send per pipe or socket and deserialize..
    – Oleg
    Commented Jun 5, 2012 at 14:07
  • @quixver: ... on the other side. In the case COM will be very good because of interface definition language originally developed in RPC (remote procedure calls). I wanted to draw your attention on the problematic.
    – Oleg
    Commented Jun 5, 2012 at 14:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.