实现一个压缩Remoting传输数据的Sink:CompressionSink (转载)

在前两讲《初探.Net Remoting服务端 Loading Remtoing配置内容的过程 》《初探.Net Remoting客户端 Loading Remtoing配置内容的过程 》中,我已经分析了Remoting 的Sink机制,接下来,就提供一个具体的范例:CompressionSink(原始SourceCode源于Advanced .Net Remoting 1StED)。 CompressionSink通过在客户端和服务端各自插入一个数据压缩-解压缩的Sink。目的是希望减少大数据量传递对网络带宽的占用,提高传输效率。下载SourceCode ,BTW,这个压缩Sink相对比较稳定,大家可以在各自的项目中放心使用。:-)



详细设计:
提供一个Assembly: CompressionSink.dll
它包括:
    客户端:
        CompressionSink.CompressionClientSinkProvider类和CompressionSink.CompressionClientSink类
    服务端:
        CompressionSink.CompressionServerSinkProvider类和CompressionSink.CompressionServerSink类
    压缩类:CompressionHelper
    压缩内核:NZipLib库。

客户端的配置文件 :

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <system.runtime.remoting>

        <application>

            <channels>

                <channel ref="http">

                    <clientProviders>

                        <formatter ref="soap" />

                        <provider type="CompressionSink.CompressionClientSinkProvider, CompressionSink" />

                    </clientProviders>

                </channel>

            </channels>

             <client>

                 <wellknown type="Service.SomeSAO, Service"  url="http://localhost:5555/SomeSAO.soap" />

             </client>

        </application>

    </system.runtime.remoting>

</configuration>

服务端的配置文件 : 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <system.runtime.remoting>

        <application>

            <channels>

                <channel ref="http" port="5555">

                    <serverProviders>

                        <provider type="CompressionSink.CompressionServerSinkProvider, CompressionSink" />

                        <formatter ref="soap"/>

                    </serverProviders>

                </channel>

            </channels>

            <service>

                <wellknown mode="Singleton"  type="Service.SomeSAO, Service"   objectUri="SomeSAO.soap" />

            </service>

        </application>

    </system.runtime.remoting>

</configuration>

 

None.gif public  class  CompressionClientSinkProvider: IClientChannelSinkProvider
ExpandedBlockStart.gifContractedBlock.gif     dot.gif {
InBlock.gif        private IClientChannelSinkProvider _nextProvider;
InBlock.gif
InBlock.gif        public CompressionClientSinkProvider(IDictionary properties, ICollection providerData) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            // not yet needed
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        public IClientChannelSinkProvider Next
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gif{
InBlock.gif                return _nextProvider;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{
InBlock.gif                _nextProvider = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            // create other sinks in the chain
InBlock.gif            IClientChannelSink next = _nextProvider.CreateSink(channel,
InBlock.gif                url,
InBlock.gif                remoteChannelData);    
InBlock.gif    
InBlock.gif            // put our sink on top of the chain and return it                
InBlock.gif            return new CompressionClientSink(next);
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }


 


 1 None.gif public  class  CompressionClientSink: BaseChannelSinkWithProperties, 
 2 None.gif                                        IClientChannelSink
 3 ExpandedBlockStart.gifContractedBlock.gif     dot.gif {
 4InBlock.gif        private IClientChannelSink _nextSink;
 5InBlock.gif
 6InBlock.gif        public CompressionClientSink(IClientChannelSink next) 
 7ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 8InBlock.gif            _nextSink = next;
 9ExpandedSubBlockEnd.gif        }

10InBlock.gif
11InBlock.gif        public IClientChannelSink NextChannelSink 
12ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
13ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gif{
14InBlock.gif                return _nextSink;
15ExpandedSubBlockEnd.gif            }

16ExpandedSubBlockEnd.gif        }

17InBlock.gif
18InBlock.gif
19InBlock.gif        public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, 
20InBlock.gif                                        IMessage msg, 
21InBlock.gif                                        ITransportHeaders headers, 
22InBlock.gif                                        Stream stream) 
23ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
24InBlock.gif
25InBlock.gif
26InBlock.gif            // generate a compressed stream using NZipLib
27InBlock.gif            stream = CompressionHelper.getCompressedStreamCopy(stream);
28InBlock.gif
29InBlock.gif            // push onto stack and forward the request
30InBlock.gif            sinkStack.Push(this,null);
31InBlock.gif            _nextSink.AsyncProcessRequest(sinkStack,msg,headers,stream);
32ExpandedSubBlockEnd.gif        }

33InBlock.gif
34InBlock.gif
35InBlock.gif        public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, 
36InBlock.gif                                            object state, 
37InBlock.gif                                            ITransportHeaders headers, 
38InBlock.gif                                            Stream stream) 
39ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
40InBlock.gif
41InBlock.gif            // deflate the response
42InBlock.gif            stream = 
43InBlock.gif                CompressionHelper.getUncompressedStreamCopy(stream);
44InBlock.gif
45InBlock.gif            // forward the request
46InBlock.gif            sinkStack.AsyncProcessResponse(headers,stream);
47ExpandedSubBlockEnd.gif        }

48InBlock.gif
49InBlock.gif
50InBlock.gif        public Stream GetRequestStream(IMessage msg, 
51InBlock.gif                                       ITransportHeaders headers) 
52ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
53InBlock.gif            return _nextSink.GetRequestStream(msg, headers);
54ExpandedSubBlockEnd.gif        }

55InBlock.gif
56InBlock.gif
57InBlock.gif        public void ProcessMessage(IMessage msg, 
58InBlock.gif                                   ITransportHeaders requestHeaders, 
59InBlock.gif                                   Stream requestStream, 
60InBlock.gif                                   out ITransportHeaders responseHeaders, 
61InBlock.gif                                   out Stream responseStream) 
62ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
63InBlock.gif            // generate a compressed stream using NZipLib
64InBlock.gif
65InBlock.gif            Stream localrequestStream  = 
66InBlock.gif                CompressionHelper.getCompressedStreamCopy(requestStream);
67InBlock.gif
68InBlock.gif            Stream localresponseStream;
69InBlock.gif            // forward the call to the next sink
70InBlock.gif            _nextSink.ProcessMessage(msg,
71InBlock.gif                                     requestHeaders,
72InBlock.gif                                     localrequestStream, 
73InBlock.gif                                     out responseHeaders, 
74InBlock.gif                                     out localresponseStream);
75InBlock.gif
76InBlock.gif            // deflate the response
77InBlock.gif            responseStream = 
78InBlock.gif                CompressionHelper.getUncompressedStreamCopy(localresponseStream);
79InBlock.gif
80ExpandedSubBlockEnd.gif        }

81ExpandedBlockEnd.gif    }

 

 1 None.gif public  class  CompressionServerSinkProvider: IServerChannelSinkProvider
 2 ExpandedBlockStart.gifContractedBlock.gif     dot.gif {
 3InBlock.gif        private IServerChannelSinkProvider _nextProvider;
 4InBlock.gif
 5InBlock.gif        public CompressionServerSinkProvider(IDictionary properties, ICollection providerData) 
 6ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 7InBlock.gif            // not yet needed
 8ExpandedSubBlockEnd.gif        }
 9InBlock.gif
10InBlock.gif        public IServerChannelSinkProvider Next
11ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
12ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gif{
13InBlock.gif                return _nextProvider; 
14ExpandedSubBlockEnd.gif            }

15ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{
16InBlock.gif                _nextProvider = value;
17ExpandedSubBlockEnd.gif            }

18ExpandedSubBlockEnd.gif        }

19InBlock.gif
20InBlock.gif        public IServerChannelSink CreateSink(IChannelReceiver channel)
21ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
22InBlock.gif            // create other sinks in the chain
23InBlock.gif            IServerChannelSink next = _nextProvider.CreateSink(channel);                
24InBlock.gif    
25InBlock.gif            // put our sink on top of the chain and return it                
26InBlock.gif            return new CompressionServerSink(next);
27ExpandedSubBlockEnd.gif        }

28InBlock.gif
29InBlock.gif        public void GetChannelData(IChannelDataStore channelData)
30ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
31InBlock.gif            // not yet needed
32ExpandedSubBlockEnd.gif        }

33InBlock.gif
34ExpandedBlockEnd.gif    }

 

None.gif using  System;
None.gif using  System.Runtime.Remoting.Channels;
None.gif using  System.Runtime.Remoting.Messaging;
None.gif using  System.IO;
None.gif
None.gif namespace  CompressionSink
ExpandedBlockStart.gifContractedBlock.gif dot.gif {
InBlock.gif
InBlock.gif    public class CompressionServerSink: BaseChannelSinkWithProperties,
InBlock.gif        IServerChannelSink
ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
InBlock.gif
InBlock.gif        private IServerChannelSink _nextSink;
InBlock.gif
InBlock.gif        public CompressionServerSink(IServerChannelSink next) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            _nextSink = next;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        public IServerChannelSink NextChannelSink 
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
InBlock.gif                return _nextSink;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, 
InBlock.gif            object state, 
InBlock.gif            IMessage msg, 
InBlock.gif            ITransportHeaders headers, 
InBlock.gif            Stream stream) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            // compressing the response
InBlock.gif            stream=CompressionHelper.getCompressedStreamCopy(stream);
InBlock.gif
InBlock.gif            // forwarding to the stack for further processing
InBlock.gif            sinkStack.AsyncProcessResponse(msg,headers,stream);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, 
InBlock.gif            object state, 
InBlock.gif            IMessage msg, 
InBlock.gif            ITransportHeaders headers)
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            return null;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, 
InBlock.gif            IMessage requestMsg, 
InBlock.gif            ITransportHeaders requestHeaders,
InBlock.gif            Stream requestStream, 
InBlock.gif            out IMessage responseMsg, 
InBlock.gif            out ITransportHeaders responseHeaders, 
InBlock.gif            out Stream responseStream) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
InBlock.gif            // uncompressing the request
InBlock.gif            Stream  localrequestStream = 
InBlock.gif                CompressionHelper.getUncompressedStreamCopy(requestStream);
InBlock.gif
InBlock.gif            // pushing onto stack and forwarding the call
InBlock.gif            sinkStack.Push(this,null);
InBlock.gif
InBlock.gif            Stream localresponseStream;
InBlock.gif            ServerProcessing srvProc = _nextSink.ProcessMessage(sinkStack,
InBlock.gif                requestMsg,
InBlock.gif                requestHeaders,
InBlock.gif                localrequestStream,
InBlock.gif                out responseMsg,
InBlock.gif                out responseHeaders,
InBlock.gif                out localresponseStream);
InBlock.gif
InBlock.gif            // compressing the response
InBlock.gif            responseStream=
InBlock.gif                CompressionHelper.getCompressedStreamCopy(localresponseStream);
InBlock.gif
InBlock.gif            // returning status information
InBlock.gif            return srvProc;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

 

 1 None.gif public  class  CompressionHelper 
 2 ExpandedBlockStart.gifContractedBlock.gif     dot.gif {
 3InBlock.gif
 4ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 5InBlock.gif        /// refactor  by zendy
 6InBlock.gif        /// </summary>
 7InBlock.gif        /// <param name="inStream"></param>
 8ExpandedSubBlockEnd.gif        /// <returns></returns>

 9InBlock.gif        public static Stream getCompressedStreamCopy(Stream inStream) 
10ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
11InBlock.gif            MemoryStream outStream = new MemoryStream();
12InBlock.gif            Deflater mDeflater = new Deflater(Deflater.BEST_COMPRESSION);
13InBlock.gif            DeflaterOutputStream compressStream = new DeflaterOutputStream(outStream,mDeflater);
14InBlock.gif
15InBlock.gif            byte[] buf = new Byte[4096];
16InBlock.gif            int cnt = inStream.Read(buf,0,4096);
17ExpandedSubBlockStart.gifContractedSubBlock.gif            while (cnt>0) dot.gif{
18InBlock.gif                compressStream.Write(buf,0,cnt);
19InBlock.gif                cnt = inStream.Read(buf,0,4096);
20ExpandedSubBlockEnd.gif            }

21InBlock.gif            compressStream.Finish();
22InBlock.gif            //modify by zendy //这个设置非常重要,否则会导致后续Sink在处理该stream时失败,在原来的源码中就是因为没有这个处理导致程序运行失败
23InBlock.gif            outStream.Seek(0,SeekOrigin.Begin);
24InBlock.gif            return outStream;
25ExpandedSubBlockEnd.gif        }

26InBlock.gif
27ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
28InBlock.gif        /// refactor  by zendy
29InBlock.gif        /// </summary>
30InBlock.gif        /// <param name="inStream"></param>
31ExpandedSubBlockEnd.gif        /// <returns></returns>

32InBlock.gif        public static Stream getUncompressedStreamCopy(Stream inStream) 
33ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
34InBlock.gif            InflaterInputStream unCompressStream = new InflaterInputStream(inStream); 
35InBlock.gif            MemoryStream outStream = new MemoryStream();
36InBlock.gif            int mSize;
37InBlock.gif            Byte[] mWriteData = new Byte[4096];
38InBlock.gif            while(true)
39ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
40InBlock.gif                mSize = unCompressStream.Read(mWriteData, 0, mWriteData.Length);
41InBlock.gif                if (mSize > 0)
42ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
43InBlock.gif                    outStream.Write(mWriteData, 0, mSize);
44ExpandedSubBlockEnd.gif                }

45InBlock.gif                else
46ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
47InBlock.gif                    break;
48ExpandedSubBlockEnd.gif                }

49ExpandedSubBlockEnd.gif            }

50InBlock.gif            unCompressStream.Close();
51InBlock.gif            //modify by zendy//这个设置非常重要,否则会导致后续Sink在处理该stream时失败,,在原来的源码中就是因为没有这个处理导致程序运行失败
52InBlock.gif            outStream.Seek(0,SeekOrigin.Begin);
53InBlock.gif            return outStream;
54ExpandedSubBlockEnd.gif        }

55ExpandedBlockEnd.gif    }


BTW,这个Sink还可以扩展,比如判断需要压缩Stream的大小,如果很大,就压缩,否则不压缩(可以在responseHeaders和requestHeaders添加是否 已经压缩的标记)

转载于:https://www.cnblogs.com/daitengfei/archive/2006/04/04/366366.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值