Named Pipes Connecting 2 different computers.

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
http://msdn.microsoft.com/en-us/library/vstudio/bb546085.aspx This is where I got the following code from.
1st let me say that it works great on a single computer. No problems. Thanks for that.
Now I want to use the code to have 2 computers communicate with each other.
Computer "A" - 192.168.1.2 and Computer "B" - 192.168.1.4
Then you come to the following comment (near the end of the web page)Robust Programming

The client and server processes in this example are intended to run on the same computer, so the server name provided to theNamedPipeClientStream object is ".". If the client and server processes were on separate computers,"." would be replaced with the network name of the computer that runs the server process.
Just change the "." to the network name of the other computer.
Now, I have spent day, and countless hours searching the net and forums for an answer on why this DOES NOT work. I have tried all the suggestions... Make an account on each system with exactly the same name and exactly the same password... set up the firewall to not block the communications... dont use the network name, but use the network address.
change "." to "A", "\A", "192.168.1.2", "\192.168.1.2" all work if the server pipe and the client pipe are on the same machine. Setting A as the server, B as the client, with all the above suggestions and combinations, does not work. Setting B as the server, A as the client, with all the above suggestions and combinations, does not work.
Could someone please give me a clear, precise, WORKING bit of code that will actually let computer A communicate with computer B?
Thanks in advance for the help.
I have marked in the client code what I assume is the offending line. Yes, I assume that it is the client that is at fault here.
SERVER CODE
Imports System
Imports System.IO
Imports System.IO.Pipes
Imports System.Text
Imports System.Threading
Public Class PipeServer
Private Shared numThreads As Integer = 4
Public Shared Sub Main()
Dim i As Integer
Dim servers(numThreads) As Thread
Console.WriteLine(vbNewLine + "*** Named pipe server stream with impersonation example ***" + vbNewLine)
Console.WriteLine("Waiting for client connect..." + vbNewLine)
For i = 0 To numThreads - 1
servers(i) = New Thread(AddressOf ServerThread)
servers(i).Start()
Next i
Thread.Sleep(250)
While i > 0
For j As Integer = 0 To numThreads - 1
If Not(servers(j) Is Nothing) Then
if servers(j).Join(250)
Console.WriteLine("Server thread[{0}] finished.", servers(j).ManagedThreadId)
servers(j) = Nothing
i -= 1 decrement the thread watch count
End If
End If
Next j
End While
Console.WriteLine(vbNewLine + "Server threads exhausted, exiting.")
End Sub
Private Shared Sub ServerThread(data As Object)
Dim pipeServer As New _
NamedPipeServerStream("testpipe", PipeDirection.InOut, numThreads)
Dim threadId As Integer = Thread.CurrentThread.ManagedThreadId
Wait for a client to connect
pipeServer.WaitForConnection()
Console.WriteLine("Client connected on thread[{0}].", threadId)
Try
Read the request from the client. Once the client has
written to the pipe its security token will be available.
Dim ss As new StreamString(pipeServer)
Verify our identity to the connected client using a
string that the client anticipates.
ss.WriteString("I am the one true server!")
Dim filename As String = ss.ReadString()
Read in the contents of the file while impersonating the client.
Dim fileReader As New ReadFileToStream(ss, filename)
Display the name of the user we are impersonating.
Console.WriteLine("Reading file: {0} on thread[{1}] as user: {2}.",
filename, threadId, pipeServer.GetImpersonationUserName())
pipeServer.RunAsClient(AddressOf fileReader.Start)
Catch the IOException that is raised if the pipe is broken
or disconnected.
Catch e As IOException
Console.WriteLine("ERROR: {0}", e.Message)
End Try
pipeServer.Close()
End Sub
End Class
Defines the data protocol for reading and writing strings on our stream
Public Class StreamString
Private ioStream As Stream
Private streamEncoding As UnicodeEncoding
Public Sub New(ioStream As Stream)
Me.ioStream = ioStream
streamEncoding = New UnicodeEncoding(False, False)
End Sub
Public Function ReadString() As String
Dim len As Integer = 0
len = CType(ioStream.ReadByte(), Integer) * 256
len += CType(ioStream.ReadByte(), Integer)
Dim inBuffer As Array = Array.CreateInstance(GetType(Byte), len)
ioStream.Read(inBuffer, 0, len)
Return streamEncoding.GetString(inBuffer)
End Function
Public Function WriteString(outString As String) As Integer
Dim outBuffer() As Byte = streamEncoding.GetBytes(outString)
Dim len As Integer = outBuffer.Length
If len > UInt16.MaxValue Then
len = CType(UInt16.MaxValue, Integer)
End If
ioStream.WriteByte(CType(len 256, Byte))
ioStream.WriteByte(CType(len And 255, Byte))
ioStream.Write(outBuffer, 0, outBuffer.Length)
ioStream.Flush()
Return outBuffer.Length + 2
End Function
End Class
Contains the method executed in the context of the impersonated user
Public Class ReadFileToStream
Private fn As String
Private ss As StreamString
Public Sub New(str As StreamString, filename As String)
fn = filename
ss = str
End Sub
Public Sub Start()
Dim contents As String = File.ReadAllText(fn)
ss.WriteString(contents)
End Sub
End Class
CLIENT CODE
Imports System
Imports System.IO
Imports System.IO.Pipes
Imports System.Text
Imports System.Security.Principal
Imports System.Diagnostics
Imports System.Threading
Public Class PipeClient
Private Shared numClients As Integer = 4
Public Shared Sub Main(Args() As String)
If Args.Length > 0 Then
If Args(0) = "spawnclient" Then
Dim pipeClient As New NamedPipeClientStream( _
".", "testpipe", _ <================== here is the offending line
PipeDirection.InOut, PipeOptions.None, _
TokenImpersonationLevel.Impersonation)
Console.WriteLine("Connecting to server..." + vbNewLine)
pipeClient.Connect()
Dim ss As New StreamString(pipeClient)
Validate the servers signature string
If ss.ReadString() = "I am the one true server!" Then
The client security token is sent with the first write.
Send the name of the file whose contents are returned
by the server.
ss.WriteString("c:textfile.txt")
Print the file to the screen.
Console.Write(ss.ReadString())
Else
Console.WriteLine("Server could not be verified.")
End If
pipeClient.Close()
Give the client process some time to display results before exiting.
Thread.Sleep(4000)
End If
Else
Console.WriteLine(vbNewLine + "*** Named pipe client stream with impersonation example ***" + vbNewLine)
StartClients()
End If
End Sub
Helper function to create pipe client processes
Private Shared Sub StartClients()
Dim i As Integer
Dim currentProcessName As String = Environment.CommandLine
Dim plist(numClients) As Process
Console.WriteLine("Spawning client processes..." + vbNewLine)
If (currentProcessName.Contains(Environment.CurrentDirectory)) Then
currentProcessName = currentProcessName.Replace(Environment.CurrentDirectory, String.Empty)
End If
Remove extra characters when launched from Visual Studio
currentProcessName = currentProcessName.Replace("", String.Empty)
currentProcessName = currentProcessName.Replace("""", String.Empty)
For i = 0 To numClients - 1
Start this program but spawn a named pipe client.
plist(i) = Process.Start(currentProcessName, "spawnclient")
Next i
While i > 0
For j As Integer = 0 To numClients - 1
If Not (plist(j) Is Nothing) Then
If plist(j).HasExited Then
Console.WriteLine("Client process[{0}] has exited.", _
plist(j).Id)
plist(j) = Nothing
i -= 1 decrement the process watch count
Else
Thread.Sleep(250)
End If
End If
Next j
End While
Console.WriteLine(vbNewLine + "Client processes finished, exiting.")
End Sub
End Class
Defines the data protocol for reading and writing strings on our stream
Public Class StreamString
Private ioStream As Stream
Private streamEncoding As UnicodeEncoding
Public Sub New(ioStream As Stream)
Me.ioStream = ioStream
streamEncoding = New UnicodeEncoding(False, False)
End Sub
Public Function ReadString() As String
Dim len As Integer = 0
len = CType(ioStream.ReadByte(), Integer) * 256
len += CType(ioStream.ReadByte(), Integer)
Dim inBuffer As Array = Array.CreateInstance(GetType(Byte), len)
ioStream.Read(inBuffer, 0, len)
Return streamEncoding.GetString(inBuffer)
End Function
Public Function WriteString(outString As String) As Integer
Dim outBuffer() As Byte = streamEncoding.GetBytes(outString)
Dim len As Integer = outBuffer.Length
If len > UInt16.MaxValue Then
len = CType(UInt16.MaxValue, Integer)
End If
ioStream.WriteByte(CType(len 256, Byte))
ioStream.WriteByte(CType(len And 255, Byte))
ioStream.Write(outBuffer, 0, outBuffer.Length)
ioStream.Flush()
Return outBuffer.Length + 2
End Function
End Class

View the full article
 
Back
Top