Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 776
  • Last Modified:

Named Pipes Issue

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
Sid Price
Asked:
Sid Price
  • 11
  • 5
1 Solution
 
käµfm³d 👽Commented:
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
 
Sid PriceAuthor Commented:
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
 
käµfm³d 👽Commented:
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
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

 
Sid PriceAuthor Commented:
Thank you, I very much appreciate you taking this time,
Sid.
0
 
käµfm³d 👽Commented:
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
 
Sid PriceAuthor Commented:
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
 
käµfm³d 👽Commented:
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
 
Sid PriceAuthor Commented:
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
 
Sid PriceAuthor Commented:
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
 
käµfm³d 👽Commented:
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
 
Sid PriceAuthor Commented:
Thanks for your continuing help, I look forward to seeing your ideas.
Sid.
0
 
Sid PriceAuthor Commented:
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
 
Sid PriceAuthor Commented:
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
 
Sid PriceAuthor Commented:
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
 
Sid PriceAuthor Commented:
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
 
Sid PriceAuthor Commented:
An answer to my issue had not been forthcoming and I was able to figure out a solution for myself.
0

Featured Post

Get your Disaster Recovery as a Service basics

Disaster Recovery as a Service is one go-to solution that revolutionizes DR planning. Implementing DRaaS could be an efficient process, easily accessible to non-DR experts. Learn about monitoring, testing, executing failovers and failbacks to ensure a "healthy" DR environment.

  • 11
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now