最近 在 工作中 遇到 公司的系统 使用的remoting方式 进行 数据传输,但是 由于 有些功能 数据传输 特别大,导致 系统比较慢。故而想到 对原系统的传输数据 进行压缩,现将经验分享一下。
大致思路是 在server端 采用Gzip方式(Gzip的好处是,对压缩数据进行了校验,保证数据的正确性,其它的压缩 方式可以自己google下))进行数据压缩,在client端进行 解压缩
1. 客户端需要实现 IClientChannelSinkProvider 和 IClientChannelSink 用法自己google,下面 是 我的 客户端实现,为了防止泄露,类名称做了改动,看的时候 注意下
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Text;
namespace XdfNis.UI.ClientProviders
{
public class ClientChannelSinkProvider : IClientChannelSinkProvider
{
private IClientChannelSinkProvider _next = null;
public ClientChannelSinkProvider() { }
public ClientChannelSinkProvider(IDictionary properties,
ICollection providerData)
{ }
// IClientChannelSinkProvider
public IClientChannelSink CreateSink(IChannelSender channel,
String url, Object remoteChannelData)
{
IClientChannelSink nextSink = null;
if (_next != null)
{
nextSink = _next.CreateSink(channel, url, remoteChannelData);
if (nextSink == null)
return null;
}
var chnl = new ClientChannelSink(nextSink);
var formatter = new BinaryClientFormatterSink(chnl);
return formatter;
}
public IClientChannelSinkProvider Next
{
get { return _next; }
set { _next = value; }
}
}
public class ClientChannelSink : BaseChannelObjectWithProperties, IClientChannelSink
{
private IClientChannelSink _nextSink = null;
public ClientChannelSink(IClientChannelSink nextSink)
: base()
{
_nextSink = nextSink;
}
public ClientChannelSink(IChannelSender channel, String url,
Object remoteChannelData, IClientChannelSink nextSink)
: base()
{
_nextSink = nextSink;
}
// IClientChannelSink
public void ProcessMessage(IMessage msg, ITransportHeaders
requestHeaders,
Stream requestStream, out ITransportHeaders responseHeaders,
out Stream responseStream)
{
// now process the message as usual
_nextSink.ProcessMessage(msg, requestHeaders, requestStream,
out responseHeaders, out responseStream);
if (responseHeaders["Compress"] != null && responseHeaders["Compress"].ToString().ToUpper() == "TRUE")
{
responseStream = CompressHelper.Decompress(responseStream);
}
}
// . . . the rest of IClientChannelSink . . .
public IClientChannelSink NextChannelSink { get { return this._nextSink; } }
public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream)
{
_nextSink.AsyncProcessRequest(sinkStack, msg, headers, stream);
}
public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream)
{
_nextSink.AsyncProcessResponse(sinkStack, state, headers, stream);
}
public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
{
return _nextSink.GetRequestStream(msg, headers);
}
}
}
2. server端
using System;
using System.Collections;
using System.Data;
using System.Runtime.Remoting.Channels;
namespace namespace
{
public class CompressionServerChannelSinkProvider : IServerChannelSinkProvider
{
private IServerChannelSinkProvider _next = null;
private readonly int _compressionThreshold;
public CompressionServerChannelSinkProvider(IDictionary properties, ICollection providerData)
{
_compressionThreshold=XX;阈值设置
}
public CompressionServerChannelSinkProvider()
{
_compressionThreshold=XX;阈值设置
}
#region IServerChannelSinkProvider Members
public IServerChannelSink CreateSink(IChannelReceiver channel)
{
IServerChannelSink nextSink = null;
if (_next != null)
{
if ((nextSink = _next.CreateSink(channel)) == null) return null;
}
return new CompressionServerChannelSink(nextSink, _compressionThreshold);
}
public void GetChannelData(IChannelDataStore channelData)
{
// Do nothing. No channel specific data.
}
public IServerChannelSinkProvider Next
{
get { return _next; }
set { _next = value; }
}
#endregion
}
}
using System.Diagnostics;
using System.IO;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Text;
namespace namespace
{
public class CompressionServerChannelSink : BaseChannelSinkWithProperties, IServerChannelSink
{
private readonly IServerChannelSink _next = null;
private readonly int _compressionThreshold;
#region IServerChannelSink Members
///
/// Constructor with properties.
///
/// Next sink.
/// Compression threshold. If less than 0, compression is disabled globally.
public CompressionServerChannelSink(
IServerChannelSink nextSink,
int compressionThreshold)
{
// Set the next sink.
_next = nextSink;
// Set the compression threshold.
_compressionThreshold = compressionThreshold;
}
public void AsyncProcessResponse(
IServerResponseChannelSinkStack sinkStack,
object state,
IMessage msg,
ITransportHeaders headers,
Stream stream)
{
// Send the response to the client.
sinkStack.AsyncProcessResponse(msg, headers, stream);
}
public Stream GetResponseStream(
IServerResponseChannelSinkStack sinkStack,
object state,
IMessage msg,
ITransportHeaders headers)
{
return null;
}
public IServerChannelSink NextChannelSink
{
get { return _next; }
}
public ServerProcessing ProcessMessage(
IServerChannelSinkStack sinkStack,
IMessage requestMsg,
ITransportHeaders requestHeaders,
Stream requestStream,
out IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
sinkStack.Push(this, null);
ServerProcessing processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders,
requestStream, out responseMsg, out responseHeaders,
out responseStream);
// If the response stream length is greater than the threshold,
// compress the stream.
if (processingResult == ServerProcessing.Complete
&& _compressionThreshold > 0
&& responseStream.Length > _compressionThreshold)
{
responseHeaders["Compress"] = "TRUE";
// Process the message and compress it.
responseStream = CompressHelper.Compress(responseStream);
}
sinkStack.Pop(this);
return processingResult;
}
#endregion
}
}
压缩算法:
public class CompressHelper
{
// The size of the buffer.
private const int BUFFER_SIZE = 4096;
public static Stream Compress(Stream inputStream)
{
Stream stream = new MemoryStream();
using (GZipStream output = new GZipStream(stream, CompressionMode.Compress, true))
{
int read;
byte[] buffer = new byte[BUFFER_SIZE];
while ((read = inputStream.Read(buffer, 0, BUFFER_SIZE)) > 0)
{
output.Write(buffer, 0, read);
}
}
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
public static Stream Decompress(Stream inputStream)
{
Stream stream = new MemoryStream();
using (GZipStream output = new GZipStream(inputStream, CompressionMode.Decompress, true))
{
int read;
byte[] buffer = new byte[BUFFER_SIZE];
while ((read = output.Read(buffer, 0, BUFFER_SIZE)) > 0)
{
stream.Write(buffer, 0, read);
}
}
// Rewind the response stream.
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
}
知乎: https://zhuanlan.zhihu.com/albertwang
微信公众号:AI-Research-Studio
下面是赞赏码