Solved

Named Pipes Issue

Posted on 2013-05-10
16
691 Views
Last Modified: 2013-06-09
I am developing a small application that needs to communicate with another process using a a named pipe. My application has a thread that waits for a connection to pipe and processes data received. This part works fine, the code creating the pipe server is:

    Private pipeServer As New NamedPipeServerStream("DebugBar_Pipe", PipeDirection.InOut, 1)

Open in new window


The input code is:

            Dim ss As New StreamReader(pipeServer, New UnicodeEncoding(False, False))
            '
            ' Wait for a client to connect
            '
            pipeServer.WaitForConnection()
            '
            While (mKeepGoing = True)
                Try
                    '
                    ' Read a line from IDBE
                    '
                    Dim strInput As String = ss.ReadLine()
                    '
                    ' Make sure we are still connected
                    '
                    If pipeServer.IsConnected = True Then
                        Debug.WriteLine(strInput)
                    Else
                        mKeepGoing = False
                    End If
                Catch e As IOException
                    Debug.WriteLine("ERROR: {0}" & vbCrLf & "{1}", e.InnerException)
                End Try
            End While
            pipeServer.Close()

Open in new window


My problem occurs when I try to send some text through the pipe to the other process, it appears that the call to write the text is queuing the text not sending it. I added a flush call and it blocks. Here is that code:

   
Public Sub Send(ByVal message As String)
        If mOutputStream Is Nothing Then
            mOutputStream = New StreamWriter(pipeServer, New UnicodeEncoding(False, False))
        End If
        If mOutputStream Is Nothing = False Then
            mOutputStream.Write(message)
            mOutputStream.Flush()
        End If
    End Sub

Open in new window


I would very much appreciate any pointers to what is wrong here.
Thank you,
Sid.
0
Comment
Question by:Sid Price
  • 11
  • 5
16 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39156229
My problem occurs when I try to send some text through the pipe to the other process, it appears that the call to write the text is queuing the text not sending it.
What gives you this impression? Is it simply the blocking behavior of the writer, or have you actually attempted to read the pipe at the other end? IIRC, you must read from the pipe in order to free up the buffer. Without reading, the pipe fills up, and you cannot write more to the pipe until the buffer has space to receive data.

Also, Flush does not appear to be supported:

http://msdn.microsoft.com/en-us/library/system.io.pipes.pipestream.flush.aspx
The Flush method is not supported in the PipeStream class and does nothing when it is called.
0
 

Author Comment

by:Sid Price
ID: 39156250
Interesting.

What I am seeing is that the "Write" call returns right away and then the "Flush" call blocks. I have removed the "Flush" call, thanks for that information.

What I am seeing at the other end of the pipe is that no data is received. That end of the pipe is read asynchronously and the event is never signaled.

I am not sure how to determine if the issue is with the pipe server or the other end. Any suggestions?
Thanks,
Sid.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39156258
I haven't played with pipes for a while now. I can't fiddle with it now, but I can take a look at it later this evening (if no one else chimes in before then).
0
 

Author Comment

by:Sid Price
ID: 39156269
Thank you, I very much appreciate you taking this time,
Sid.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39157548
See if the attached project sheds any light on the issue. I've created a "reader" and "writer" project. The "writer" creates the pipe server, and the "reader" creates a pipe client to connect to the server. It's a very contrived example, but it appears to function correctly.
28124575---NamedPipeExample.zip
0
 

Author Comment

by:Sid Price
ID: 39158175
Thank you.
Unfortunately I cannot open the projects, VS 2010 says the two projects are "incompatible" a message I have never seen before.
What version of VS did you create these projects with?
Sid.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39158245
Oh, sorry. I have Visual Studio 2012 Express installed. The code for each is thus:

Server
Imports System.IO.Pipes

Module Module1
    Private pipeServer As New NamedPipeServerStream("DebugBar_Pipe", PipeDirection.InOut, 1, PipeTransmissionMode.Byte)

    Sub Main()
        Dim messages() As String = {"HELLO", "HOW'S THE WEATHER THERE?", "I HAVE TO GO NOW"}

        pipeServer.WaitForConnection()

        For i As Integer = 0 To messages.Length - 1
            Dim msgBytes() As Byte = Text.Encoding.ASCII.GetBytes(messages(i))

            pipeServer.Write(msgBytes, 0, msgBytes.Length)
            System.Threading.Thread.Sleep(3000) ' Simulate work that would slow writing to the pipe
        Next

        'pipeServer.WaitForPipeDrain()
        pipeServer.Disconnect()
    End Sub

End Module

Open in new window


Client
Imports System.IO.Pipes

Module Module1
    Private pipeClient As New NamedPipeClientStream("DebugBar_Pipe")

    Sub Main()
        pipeClient.Connect()

        While pipeClient.IsConnected
            Dim bytesRead As Integer

            Do
                Dim s As String
                Dim buffer(32) As Byte

                System.Threading.Thread.Sleep(1000) ' Simulate other logic that would slow the reading of the pipe
                bytesRead = pipeClient.Read(buffer, 0, 32)
                s = Text.Encoding.ASCII.GetString(buffer)
                Console.WriteLine(s)
            Loop While bytesRead > 0
        End While
    End Sub

End Module

Open in new window

0
 

Author Comment

by:Sid Price
ID: 39158247
I created new projects and added your sources and did some testing. The issue with my server code appears to be that I have a thread that is blocking on the reading of the pipe and this prevents me from writing to the pipe.
I need to be listening for data on my server and while listening I need to be able to send data through the pipe.
This needs some restructuring of the code ... I will let you know how that goes, thanks,
Sid.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:Sid Price
ID: 39158363
There does not appear to be anyway to "peek" into a NamedPipeServerStream and when I try to peek on my StreamReader it always returns saying there is data when there is not. This is what I tried:

            Dim ss As New StreamReader(pipeServer, New UnicodeEncoding(False, False))
            '
            ' Wait for a client to connect
            '
            pipeServer.WaitForConnection()
            '
            While (mKeepGoing = True)
                Try
                    '
                    ' Read a line from IDBE
                    '
                    If ss.Peek > -1 Then
                        Dim strInput As String = ss.ReadLine()
                        '
                        ' Make sure we are still connected
                        '
                        If pipeServer.IsConnected = True Then
                            Debug.WriteLine(strInput)
                        Else
                            mKeepGoing = False
                        End If
                    Else
                        Thread.Sleep(10)
                    End If
                Catch e As IOException
                    Debug.WriteLine("ERROR: {0}" & vbCrLf & "{1}", e.InnerException)
                End Try
            End While

Open in new window


I need to only call "ReadLine" when there is data, if there is no data I can sleep for a short time to allow the write operations to be executed.

Just to be clear I need a pipe server that is listening for input and is able to write to the pipe when data is available.
Thanks,
Sid
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39158515
I'm going to be off-grid for a bit as I am reinstalling my OS. Once I get everything set back up, I can try to work up something close to what you've described.
0
 

Author Comment

by:Sid Price
ID: 39160065
Thanks for your continuing help, I look forward to seeing your ideas.
Sid.
0
 

Author Comment

by:Sid Price
ID: 39172103
Hello "kaufmed", I was wondering if you were back online yet as I am still in need of help with my problem :o(

Thanks,
Sid.
0
 

Author Comment

by:Sid Price
ID: 39194233
Hello,
I need to make some progress with this application so I have a question about asynchronous operation of named pipes.
If I take the time to change my blocking design to be asynchronous will my issue be resolved. In other words would my application be able to listen for incoming data and at the same time be able to write to the pipe. This is a read/write pipe of course.
Thanks,
Sid.
0
 

Author Comment

by:Sid Price
ID: 39216541
Could someone confirm that if I implement asynchronous read/write in my pipe application that I will be able to send data to the pipe while waiting for incoming data? I need my application to listen for input and still be able to send commands out of the pipe. This appears to not be possible with blocking calls and before I expend the effort on converting to non--blocking I would like to know that it should work.
Thanks,
Sid.
0
 

Accepted Solution

by:
Sid Price earned 0 total points
ID: 39220714
I have resolved my pipe issues by reverting to using the WIN32 API for named pipes. Here is the code that I have and while it needs a little more work it is basically working.

            While (mKeepGoing = True)
                Try
                    Dim inputBytes(1024) As Byte
                    Dim tbRead As Integer
                    Dim tbAvailable As Long
                    '
                    ' Any incoming data available?
                    '
                    If PeekNamedPipe(mPipe, inputBytes, inputBytes.Length, tbRead, tbAvailable, IntPtr.Zero) <> 0 Then
                        If tbAvailable <> 0 Then
                            '
                            ' Process the input
                            '
                            ReadFile(mPipe, inputBytes, inputBytes.Length, tbRead, IntPtr.Zero)
                        End If
                    End If
                    '
                    ' Anything in the output queue?
                    '
                    If mOutputQueue.Count <> 0 Then
                        While mOutputQueue.Count <> 0
                            Dim strOutput = mOutputQueue.Dequeue
                            Dim msgBytes() As Byte = Text.Encoding.Unicode.GetBytes(strOutput)
                            Dim tbWritten As Integer
                            WriteFile(mPipe, msgBytes, msgBytes.GetLength(0), tbWritten, IntPtr.Zero)
                        End While
                    End If
                Catch e As IOException
                    Debug.WriteLine("ERROR: {0}" & vbCrLf & "{1}", e.InnerException)
                End Try
            End While

Open in new window


The biggest issue is to add some sleep time so that this thread doesn't burn too much CPU time as it spins in this loop.

Thanks to all who gave input, this is such a great forum,
Sid.
0
 

Author Closing Comment

by:Sid Price
ID: 39232764
An answer to my issue had not been forthcoming and I was able to figure out a solution for myself.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now