C#
// Open the named pipe. var server = new NamedPipeServerStream("NPtest"); Console.WriteLine("Waiting for connection..."); server.WaitForConnection(); Console.WriteLine("Connected."); var br = new BinaryReader(server); var bw = new BinaryWriter(server); while (true) { try { var len = (int) br.ReadUInt32(); // Read string length var str = new string(br.ReadChars(len)); // Read string Console.WriteLine("Read: \"{0}\"", str); str = new string(str.Reverse().ToArray()); // Just for fun var buf = Encoding.ASCII.GetBytes(str); // Get ASCII byte array bw.Write((uint) buf.Length); // Write string length bw.Write(buf); // Write string Console.WriteLine("Wrote: \"{0}\"", str); } catch (EndOfStreamException) { break; // When client disconnects } } Console.WriteLine("Client disconnected."); server.Close(); server.Dispose();
Python
In this example, I implement a very simple protocol, where every "message" is a 4-byte integer (import time import struct f = open(r'\\.\pipe\NPtest', 'r+b', 0) i = 1 while True: s = 'Message[{0}]'.format(i) i += 1 f.write(struct.pack('I', len(s)) + s) # Write str length and str f.seek(0) # EDIT: This is also necessary print 'Wrote:', s n = struct.unpack('I', f.read(4))[0] # Read str length s = f.read(n) # Read str f.seek(0) # Important!!! print 'Read:', s time.sleep(2)
UInt32
in C#, 'I'
(un)pack format in Python), which indicates the length of the string that follows. The string is ASCII.
Important things to note here:
- Python
- The third parameter to
open()
means "unbuffered". Otherwise, it will default to line-buffered, which means it will wait for a newline character before actually sending it through the pipe. - I'm not sure why, but omitting the
seek(0)
will cause an IOError #0. I was clued to this by a StackOverflow question.
References:
- .NET
NamedPipeServerStream
class on MSDN - Python
open()
method on Python.org
I have followed you example, but keep getting a broken pipe error on the c# side after the number of characters in the message changes. For example when it goes from Message[9] to Message[10], a broken pipe error is thrown by C# and nothing is sent back to python.
ReplyDeleteDo you know what might be causing this?
I finally got back to this problem and fixed it. It turns out the f.seek(0) is necessary after writing to the pipe also. See the EDIT in the python source code. This probably has to do with something the python file implementation is doing under the hood.
DeleteGood catch! Apparently I never waited the 20 seconds to get to that point - sorry for taking so long to fix this!
This comment has been removed by the author.
Deletehelp me:
DeleteTraceback (most recent call last):
File "C:\Users\Son\Desktop\Namedpipe", line 4, in
f = open(r'\\.\pipe\NPtest', 'r+b', 0)
IOError: [Errno 2] No such file or directory: '\\\\.\\pipe\\NPtest'
What about the other way around? That is, creating the named pipe (server) in Python and the client in C#? My question is mainly how to know that a client as connected to the other end of the pipe, when using open in Python to create the pipe!
ReplyDeleteAlmost 10 years later and thanks for just writing it down cause this was the one example I've found that actually works.
ReplyDelete