.net romoting 数据压缩

最近 在 工作中 遇到 公司的系统 使用的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


        /// <summary>
        /// Constructor with properties.
        /// </summary>
        /// <param name="nextSink">Next sink.</param>
        /// <param name="compressionThreshold">Compression threshold. If less than 0, compression is disabled globally.</param>
        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

https://i-blog.csdnimg.cn/blog_migrate/5509f60f875d387159a310532cc257dd.png ​​

下面是赞赏码

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值