|
||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||
Inter-Process Communication in .NET Using Named Pipes, Part 14. Connecting Client PipesThe server Named Pipe needs to be set in a listening mode in order for client pipes to connect to it. This is done by calling the NamedPipeNative.ConnectNamedPipe method. Because our pipe was created in a blocking mode, calling this method will put the current thread in waiting mode until a client pipe attempts to make a connection. A client Named Pipe is created and connected to a listening server pipe by calling the NamedPipeNative.CreateFile method, which in turn calls the corresponding Kernel32 method. The code below, part of NamedPipeWrapper.ConnectToPipe illustrates that. public static PipeHandle ConnectToPipe(string pipeName,
string serverName) {
PipeHandle handle = new PipeHandle();
// Build the name of the pipe.
string name = @"\\" + serverName + @"\pipe\" + pipeName;
for (int i = 1; i<=ATTEMPTS; i++) {
handle.State = InterProcessConnectionState.ConnectingToServer;
// Try to connect to the server
handle.Handle = NamedPipeNative.CreateFile(name,
NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE,
0, null, NamedPipeNative.OPEN_EXISTING, 0, 0);
After we create a PipeHandle object and build the pipe name, we call the NamedPipeNative.CreateFile method to create a client Named Pipe and connect it to the specified server pipe. In our example the client pipe is configured to cater for both reading and writing. If the client pipe is created successfully, the CreateFile method returns the native handle corresponding to the client Named Pipe, which we are going to use in subsequent operations. If for some reason the client pipe creation failed, the method would return -1, which is set to be the value of the INVALID_HANDLE_VALUE constant. There is one more thing that needs to be done before the client Named Pipe can be used for reading and writing. We need to set its handle mode to PIPE_READMODE_MESSAGE, which will allow us to read and write messages. This is done by calling NamedPipeNative.SetNamedPipeHandleState:
if (handle.Handle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE) {
// The client managed to connect to the server pipe
handle.State = InterProcessConnectionState.ConnectedToServer;
// Set the read mode of the pipe channel
uint mode = NamedPipeNative.PIPE_READMODE_MESSAGE;
if (NamedPipeNative.SetNamedPipeHandleState(handle.Handle,
ref mode, IntPtr.Zero, IntPtr.Zero)) {
break;
}
Each client pipe communicates with an instance of the server pipe. If the server pipe has reached its maximum number of instances, then creating a client pipe will return an error. In such case it is useful to check for the error type, wait for some time and then make another attempt to create the client Named Pipe. Checking for the error type is done by the NamedPipeNative.GetLastError method:
if (NamedPipeNative.GetLastError() ==
NamedPipeNative.ERROR_PIPE_BUSY)
NamedPipeNative.WaitNamedPipe(name, WAIT_TIME);
.NET Named Pipes Discussion
|
|||||||||||||
| © 2009 by Ivan Latunov. Disclaimer. | |||||||||||||