Промежуточная среда .NET Remoting
Труба шифрования клиента должна зашифровать этот поток перед отправкой на сервер и расшифровать при получении ответа сервера.
class EncryptedClientChannelSink: IClientChannelSink
{
public IDictionary Properties
{
get { return null; }
}
private IClientChannelSink nextSink;
public IClientChannelSink NextChannelSink
{
get { return nextSink; }
}
private SymmetricEncryptor encryptor;
public EncryptedClientChannelSink(SymmetricEncryptor channelEncryptor,
IClientChannelSink next)
{
encryptor = channelEncryptor;
nextSink = next;
}
public void ProcessMessage(IMessage message,
ITransportHeaders requestHeaders, Stream requestStream,
out ITransportHeaders responseHeaders, out Stream responseStream)
{
MemoryStream encryptedStream = new MemoryStream();
Stream serverStream = null;
// Зашифровать запрос клиента
encryptor.Encrypt(requestStream, encryptedStream);
encryptedStream.Position = 0;
nextSink.ProcessMessage(message, requestHeaders, encryptedStream,
out responseHeaders, out serverStream);
serverStream = Utils.ReadAllStream(serverStream);
// Расшифровать ответ сервера
responseStream = new MemoryStream();
encryptor.Decrypt(serverStream, responseStream);
responseStream.Position = 0;
}
public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
{
return null;
}
public void AsyncProcessRequest(IClientChannelSinkStack sinkStack,
IMessage message, ITransportHeaders headers, Stream stream)
{
throw new NotSupportedException();
}
public void AsyncProcessResponse(
IClientResponseChannelSinkStack sinkStack, object state,
ITransportHeaders headers, Stream stream)
{
throw new NotSupportedException();
}
} // EncryptedClientChannelSink
Листинг
8.3.
Вспомогательный класс Utils служит для считывания всего содержимого потока, не поддерживающего свойство Length.
public static class Utils
{
public static MemoryStream ReadAllStream(Stream input)
{
byte[] buffer = new byte [1024];
MemoryStream output = new MemoryStream();
while (true)
{
int read = input.Read(buffer, 0, buffer.Length);
output.Write(buffer, 0, read);
if (read < buffer.Length) break;
}
output.Position = 0;
return output;
}
}
}
// SevaRemotingEncrypted.csДля компиляции указанных файлов можно использовать следующий make-файл.
makefile : Client.exe SevaRemotingEncrypted.dll
common = Seva*.cs
Client.exe : Client.cs RemoteService.dll
csc /r:RemoteService.dll Client.cs
RemoteService.dll : RemoteService.cs
csc /t:library RemoteService.cs
SevaRemotingEncrypted.dll: $(common)
csc /out:SevaRemotingEncrypted.dll /t:library $(common)Как видно из данного файла, при компиляции клиент не ссылается на сборку с модифицированными поставщиками труб. Регистрация данных поставщиков труб происходит с помощью файлов конфигурации.
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown
type="RemoteService.RemoteServiceTest, RemoteService"
url="tcp://localhost:10020/endpoint"
/>
</client>
<channels>
<channel ref ="tcp">
<clientProviders>
<formatter ref="binary"/>
<provider type="Seva.Remoting.Encryption.
EncryptedClientChannelSinkProvider, SevaRemotingEncrypted"
key="secret.key"
/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>Таким образом, архитектура .NET Remoting позволяет встраивать собственные трубы в канал Remoting, причем для этого не требуется что либо менять в коде клиента или сервера. Однако даже в простейшем случае реализация собственных поставщиков и труб выглядит достаточно громоздко.