3

So I seem to be having a similar problem to this question : Named pipes performance issues

I have no problem sending from C# -> Delphi. But the moment Delphi has to send to me, the entire world ends and I have no idea why. All read operations block forever unless the Delphi client disconnects. :-(

        var stream = new NamedPipeClientStream(".",
                         PipeName,
                         PipeDirection.InOut,
                         PipeOptions.Asynchronous);
        stream.Connect();
        stream.ReadMode = PipeTransmissionMode.Message; // Have tried Byte

Pipe.InBufferSize is always 0. Nothing ever comes through from Delphi, at all. The moment I try to Pipe.Read() it freezes/blocks until ResurrectionOfChrist == true.

I have a thread calling :

    protected static byte[] ReadMessage(PipeStream stream)
    {
        MemoryStream memoryStream = new MemoryStream();

        byte[] buffer = new byte[BUFFER_SIZE];

        do
        {
            stream.Read(buffer, 0, BUFFER_SIZE); // Freezes here (not the loop)
            memoryStream.Write(buffer, 0, buffer.Length);
        } while (stream.IsMessageComplete == false);

        return memoryStream.ToArray();
    }        

Wondering if anyone has any experience with this Libby's Pipes.PAS and .NET?

I know Libby's defines the following ... I'm not sure if this is what I need to implement.. the problem is, I can't get a single Byte out of the damn Pipe.

////////////////////////////////////////////////////////////////////////////////
// Mutliblock message constants
////////////////////////////////////////////////////////////////////////////////
const
    MB_MAGIC  = $4347414D; // MAGC
    MB_START  = $424D5453; // STMB
    MB_END    = $424D5445; // ETMB
    MB_PREFIX = 'PMM';

EDIT: [Per Requested Info] So I don't have the source that writes to the pipe (I will try to get it), but I do have the Delphi source that reads from it (What I'm trying to port to C#)

  if not Assigned(NamedPipe) then
  begin
    NamedPipe := TPipeClient.Create(nil);
    NamedPipe.PipeName := 'MyProc_' + IntToStr(GetCurrentProcessId);
    NamedPipe.OnPipeMessage := OnPipeMsg;
    NamedPipe.Connect(5000);
  end;

procedure OnPipeMsg(Sender : TObject; Pipe : HPIPE; Stream : TStream);
MyStream.CopyFrom(Stream);

For the life of me I can't seem to understand where I'm going wrong.

EDIT2:

Delphi Pipes Source being used is from :
http://francois-piette.blogspot.com/2013/04/inter-process-communication-using-pipes.html
located :
http://www.overbyte.be/frame_index.html?redirTo=/blog_source_code.html
4
  • Has the pipe been secured? Commented Aug 30, 2013 at 9:08
  • Please post the Delphi code which writes to the pipe. Commented Aug 30, 2013 at 9:29
  • Added some info for you both ... I'll try to get the TPipeServer code... but for now I think we can assume it is as simple as the delphi client code i posted. Commented Aug 30, 2013 at 16:29
  • Added links to the pipes.pas source ... Pretty desperate for some ideas here. Commented Aug 30, 2013 at 22:07

1 Answer 1

2

So I got everything working, and here are some lessons when interfacing with Libby's Pipes.PAS :

  1. NamedPipeClientStream.IsMessageComplete will not work for you, ever. At least, it doesn't for me.
  2. Your reading thread/function needs to look something like :
while(true)
{
   if(pipeClient.CanRead)
   {
       byte[] buffer = new byte[BUFFER_SIZE];
       int bytesRead = pipeClient.Read(buffer, 0, BUFFER_SIZE);
       if(bytesRead > 0)
          ... Do stuff
   }
}
  1. Libbys uses a custom protocol to signal multi-block sends :

Multi-Block Start Packet:

* 0x10 0x00 0x00 0x00 (4 bytes for length ... decimal 16)
* 0x4d 0x41 0x47 0x43 (4 bytes for "MB_MAGIC" ... ASCII is "MAGC")
* 0x53 0x54 0x4d 0x42 (4 bytes for "MB_START" control ... ASCII is "STMB" for Start Multi-block)
* 0x4d 0x41 0x47 0x43 (4 bytes for "MB_MAGIC" again)

// Everything inbetween is what you keep

Multi-Block End Packet:

* 0x10 0x00 0x00 0x00 (4 bytes for length ... decimal 16)
* 0x4d 0x41 0x47 0x43 (4 bytes for "MB_MAGIC" ... ASCII is "MAGC")
* 0x45 0x54 0x4d 0x42 (4 bytes for "MB_END" control ... ASCII is "ETMB" for End Multi-block)
* 0x4d 0x41 0x47 0x43 (4 bytes for "MB_MAGIC" again)

Oh and in case you are wondering what arguments you want for the pipe :

pipeClient = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous, System.Security.Principal.TokenImpersonationLevel.Anonymous);

Feel free to comment if you have other questions. It is 7:00am and I haven't slept, so I'm not sure what I've left out.

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