|
||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||
Inter-Process Communication in .NET Using Named Pipes, Part 15. Writing and Reading DataNamed Pipes do not support stream seeking, which means that when reading from a named pipe we cannot determine in advance the size of the message. As a workaround a simple message format is introduced, which allows us to first specify the length of the message and then read or write the message itself. Our solution will not need to cater for very large messages so we are going to use a System.Int32 variable to specify the message length. In order to represent an Int32 we need four bytes, so the first four bytes of our messages will always contain the message length. 5.1. Writing Data to a Named PipeThe NamedPipeWrapper.WriteBytes method below writes a message to a Named Pipe, represented by the handle provided as an input parameter. The message itself has been converted to bytes using UTF8 encoding and is passed as a bytes array. public static void WriteBytes(PipeHandle handle, byte[] bytes) {
byte[] numReadWritten = new byte[4];
uint len;
if (bytes == null) {
bytes = new byte[0];
}
if (bytes.Length == 0) {
bytes = new byte[1];
bytes = System.Text.Encoding.UTF8.GetBytes(" ");
}
Get the length of the message: len = (uint)bytes.Length; handle.State = InterProcessConnectionState.Writing; Get the bytes representation of the message length and write those four bytes first:
if (NamedPipeNative.WriteFile(handle.Handle,
BitConverter.GetBytes(len), 4, numReadWritten, 0)) {
Write the rest of the message:
if (!NamedPipeNative.WriteFile(handle.Handle, bytes,
len, numReadWritten, 0)) {
handle.State = InterProcessConnectionState.Error;
throw new NamedPipeIOException("Error writing to pipe.
Internal error: " + NamedPipeNative.GetLastError().ToString(),
NamedPipeNative.GetLastError());
}
}
else {
handle.State = InterProcessConnectionState.Error;
throw new NamedPipeIOException("Error writing to pipe.
Internal error: " + NamedPipeNative.GetLastError().ToString(),
NamedPipeNative.GetLastError());
}
handle.State = InterProcessConnectionState.Flushing;
Finally flush the pipe. Flushing the Named Pipe ensures that any buffered data is written to the pipe and will not get lost. Flush(handle); handle.State = InterProcessConnectionState.FlushedData; } 5.2. Reading from a Named PipeIn order to read a message from a Named Pipe we first need to find its length by converting the first four bytes to an integer. Then we can read the rest of the data. The NamedPipeWrapper.ReadBytes method below illustrates that. public static byte[] ReadBytes(PipeHandle handle, int maxBytes) {
byte[] numReadWritten = new byte[4];
byte[] intBytes = new byte[4];
byte[] msgBytes = null;
int len;
handle.State = InterProcessConnectionState.Reading;
handle.State = InterProcessConnectionState.Flushing;
Read the first four bytes and convert them to an integer:
if (NamedPipeNative.ReadFile(handle.Handle, intBytes,
4, numReadWritten, 0)) {
len = BitConverter.ToInt32(intBytes, 0);
msgBytes = new byte[len];
handle.State = InterProcessConnectionState.Flushing;
Read the rest of the data or throw an exception:
if (!NamedPipeNative.ReadFile(handle.Handle, msgBytes, (uint)len,
numReadWritten, 0)) {
handle.State = InterProcessConnectionState.Error;
throw new NamedPipeIOException("Error reading from pipe.
Internal error: " + NamedPipeNative.GetLastError().ToString(),
NamedPipeNative.GetLastError());
}
}
else {
handle.State = InterProcessConnectionState.Error;
throw new NamedPipeIOException("Error reading from pipe.
Internal error: " + NamedPipeNative.GetLastError().ToString(),
NamedPipeNative.GetLastError());
}
handle.State = InterProcessConnectionState.ReadData;
if (len > maxBytes) {
return null;
}
return msgBytes;
}
.NET Named Pipes Discussion
|
|||||||||||||
| © 2009 by Ivan Latunov. Disclaimer. | |||||||||||||