Sunday, August 11, 2013

Using Pipes for Intranet Communication in .Net

Inter-process communication using Pipes in .Net

IPC or Inter process communication is technique of sharing information or logic with multiple process or threads which may be one single machine or spanning across different machines, all working in sync or harmony.
To establish this synchronous behavior there has to be established boundary within which information exchange need to occur.
Few of the techniques are -
·  Pipes
· Signals
· Message Queues
· Semaphores
· Shared Memory
· Sockets
Every technique have their own pros and cons. Being a net coder,I will be discussing on pipes from net perspective.
Pipes are one of the most reliable communication used in software architecture. It helps to solve most of the requirement which is related to information exchange within a intranet or group of computer.

This is how Microsoft describes it "Named pipes provide inter process communication between a pipe server and one or more pipe clients. They offer more functionality than anonymous pipes, which provide inter process communication on a local computer. Named pipes support full duplex communication over a network and multiple server instances, message-based communication, and client impersonation, which enables connecting processes to use their own set of permissions on remote servers."

Pipes are best suited for scenarios like -
1. IPC within Intranet.
2. Fast, efficient and reliable connection oriented communication.
3. Socket like connectivity with no threats of opening port.
4. Communication with native apps.
5. Scalability
Using Pipe is extremely easy and conventionally equivalent to accessing file although security must be taken care off. Developer can make use of in house security mechanism inside Pipe to authenticate a caller and grant required access to a particular process. The best feature of scalability meaning if your application have several independent information sharing modules and if connected by pipes, it’s possible to span one low performant module into multiple computers and have a load balanced approach to share task between them.
Here are the very basics of pipes.

1. Identifying which pipe to be used

 Net provides two pipes (taking MSDN description)

Anonymous pipes provides inter-process communication on a single computer. Anonymous pipes require less overhead than named pipes. They are one-way and cannot be used over a network. They support only a single server instance. Anonymous pipes are useful for communication between threads, or between parent and child processes where the pipe handles can be easily passed to the child process when it is created.

Named pipes provide inter-process communication between a pipe server and one or more pipe clients. Named pipes can be one-way or duplex. They support message-based communication and allow multiple clients to connect simultaneously to the server process using the same pipe name. Named pipes also support impersonation, which enables connecting processes to use their own permissions on remote servers.
The above description describes pretty much what should be used as requirement.

2. Instantiating/Creating Pipe

All the pipes are available in their respective stream, depending upon what you need to be configured e.g. server or client use the respective stream
Below example is of Named pipe, anonymous pipe being virtually same with different parameters.

NamedPipeServerStream _ServerStream = new NamedPipeServerStream(pipename, PipeDirection.InOut, totalNumberofClients);
NamedPipeClientStream _ClientStream = new NamedPipeClientStream(serverName, pipename, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation);

3. Using pipe

Having created the pipe one can easily read of write in the stream using various methods available.

 override int Read(byte[] buffer, int offset, int count);
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state);

Or it can be used as native Stream class. Since both server can client uses stream they can be wrapped under same implementation.

Step by Step to Implement Pipe

1. Goal - To create a IPC between Hub and several clients in which hub should be able to assign task and control client to execute and aggregate result,as shown below-

2. Create Library for Hub and Client.
Since Hub should be connecting to different client making hub use server stream will put us under constraint of asking client to connect to server which is difficult to debug.
What I meant here is-
ServerStream - Wait for connection 
Client Stream - Attempts to connect to server
So here Hub should be attempting to connect to different clients urging us to use ClientStream for Hub.Since both have similar stream base class we can create an DI or basing argument check to distinguish which stream should be used for Hub to make it reusable.

3.Keeping Dialog in sequence.
To keep it simple say server will be attempting to do same operation in all the client.Then server and client should be following a sample operation names/sequence to distinguish the server message.
We will keep it simple 
Let say we have a initialize operation to run from hub, the sequence will be-
Client waits.
Server write string "Initialize" to all pipes.
Server waits.
Clients read the string and run the logic of initialize.
Client waits.
Server writes model of type T to client.
Server waits.
Client reads for model of type T.
Client writes "InitializeOK"
Server reads and declares Initialization is complete.

Its a simple scenario of server asking client to run the process of initialize and then writes the model to pass data while client gets the data model and run the logic while replying OK.

For single client Hub can wait for OK message but to handle multiple threads each waiting for Client response can be  synchronized with CountdownEvent.
4. Perform Finish Operation
Hub should be able to send finish signal to client for releasing all the objects held in client side and if required.

There is full working code which is implemented using Task (await/async) and provides a wrapper for Client and Server stream.Check out the code @

Few things to watch out for-

1. Most of the operations in pipes are async - which means for a particular instance of pipe, only one out of read and write can be executed. Executing read and write simultaneously can cause pipe to go in endless wait.

2.The read and write operation between server and client should be synchronized, e.g when client is waiting server should be writing next and vice versa. If both go in read state than pipe is again unusable.

3. In Intranet the name of pipe should be  "\\" + <ServerName>+ @"\pipe\" + <pipeName>

No comments:

Post a Comment