Apr 19, 2011

Using PipeTransmissionMode.Message with Named Pipes in .NET

Summary



If you wish to use PipeTransmissionMode.Message instead of PipeTransmissionMode.Byte for your named pipes, the NamedPipeServerStream must be created with a PipeDirection parameter of PipeDirection.InOut:

Server Code:


using (NamedPipeServerStream ps = new NamedPipeServer("myPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.None))
{
ps.WaitForConnection(); // no sense writing to the pipe until there is a client to read from it.
...
// this would likely be enclosed in some kind of loop to pass messages to the client.
string msg = "Hello, client!";
byte[] msgBuff = System.Text.Encoding.UTF8.GetBytes(message);
ps.Write(msgBuff, 0, msgBuff.Length);
...
}

Client Code:


public const int BUFFSIZE = 1024; // or whatever

using (NamedPipeClientStream cs = new NamedPipeClientStream("myPipe"))
{
cs.Connect(); // connect to the pipe server
cs.ReadMode = PipeTransmissionMode.Message;
// read one message from the server
int byteCount = 0;
byte[] msgBuff = new byte[BUFFSIZE];
StringBuilder mb = new StringBuilder();
do {
byteCount = cs.Read(buff, 0, BUFFSIZE);
mb.Append(System.Text.Encoding.UTF8.GetString(buff, 0, count);
} while (!(cs.IsMessageComplete));
string msg = mb.ToString();
// do something with the message
Console.WriteLine("Message received from server: {0}", msg);
// would print "Hello, client!" on the client's console.
}


Discussion



It may be odd, but for some reason, a NamedPipeServerStream must be created with a PipeDirection parameter of InOut in order for PipeTransmissionMode.Message to work. Not only is this not directly documented, but the way the error is reported is completely counter-intuitive, and appears to have nothing to do with the pipe's TransmissionMode.

Not Directly Documented



The closest to this being "documented behavior" is a blog post by Microsoft's BCL team here. (See the third example of the post.) The example shows the code, but does not explain why the server's pipe must be in/out. None of the rest of the named pipes documentation indicates why this is.

Counter-Intuitive



I like .NET in general in part because of its discoverability: With the code completion support and "pop-up" signature documentation, it is generally possible to discover how to use a Framework object without having to consult the documentation. This behavior, however, is completely counter-intuitive.

First of all, a pipe's direction and whether it's operating in message/byte mode appear completely orthogonal. Why a server's pipe has to be in/out is not explained. Second, the exception that occurs when you get it wrong does not appear to have anything to do with ... well, anything: The client gets an "UnauthorizedAccessException" when attempting to Connect() its pipe.

This is wrong it at least three respects: It's the server's mistake, not the client's; it occurs when connecting, rather than when trying to set the client's ReadMode; and what does access authorization have anything to do with TransmissionMode, anyway? I could understand such an exception if a client tried to use the same mode as the server (it wouldn't work very well for both the client and the server to open the pipe for reading, for example).

The specific exception message is likewise uninformative: "Access to the path is denied." That sounds like a permissions issue, but when I'm testing this, I'm running two processes in parallel under the same user id: no permissions conflict should even be possible.

I hope this helps someone.

Apr 12, 2011

Welcome

Welcome to my blog.

I tried to start blogging a couple of years ago, but got scared and stopped. I'm scared now, trying to start again. Once I hit that 'Publish' button, ... well, I just don't know. I might be liked, I might be hated. Perhaps worst of all, and most likely, is that I'll just be ignored.

But I'm going to try again. And again after that, if necessary. I believe I have something of value to share with the world, and right now this is the best (only?) outlet I'm aware of. Of course, just because I believe it has value doesn't make it so. And I cannot think of any way to know ahead of time whether what I write will have value to you, or anyone else. So, let me throw some stuff out there, and "let the market decide".

What is this blog about, anyway?


Overall, this blog is about me sharing my experiences with the world, and hoping that my sharing will help someone in some way. It's also about me refining my ideas: I find that quite often I don't completely understand my views on a given topic until I try to explain them to someone else.

In particular, it is about technology and philosophy, computers and society, programming and psychology. I've been programming professionally for the better part of twenty years; surely I've learned something of value. I'm quite the armchair philosopher, too: I love to try to figure out why we do what we do, and lately I've been wanting to formalize the principles I try to live by, to generate a sort of personal Constitution, if you will.

Thanks for reading this.

BM