基于WCF的通道网络传输数据压缩技术的应用研究

简介:
本文及程序不是介绍WCF怎么用,而是研究如何在WCF通信时的通道两端自动进行数据压缩和解压缩,从而增加分布式数据传输速度。
 
而且,这个过程是完全透明的,用户及编程人员根本不需要知道它的存在,相当于HOOK在两端的一个组件。可以使用中网络带宽较小
的网络环境中。当WCF在两个实体间通讯的时候,便自动创建一个信息通道转接通讯,这个消息包含数据请求和相应。WCF使用特殊的
编码器将请求和响应数据转换成一系列的字节。
 
    我所带的项目里遇到大文件分布式传输问题,经过分析考虑采用WCF通道压缩技术来解决此问题。执行这样的编码是需要传输大文件(XML格式)由一台机器到另一台机器传输,而连接有速度限制。经过查看了一些国外英文网站,发现我不用写一个特殊的函数边压缩和边解压,而是配置传输通道可以做到这一点,这种方式压缩可重复使用的任何契约。我发现自己编写的消息编码器是最简单的方式来实现功能,真正的问题是如何编写信息编码器,在MSDN上没有找到任何关于此应用的实例。消息契约编码器的想法是Hook连接两端发送和接收信息的渠道。程序是采用Microsoft Visual Studio 2008 WCF设计。
              
                                   图1 WCF消息通道编码过程时序图    
 
发送方:代码中加入方法,该方法及其参数的序列化成SOAP消息,消息编码序列化的信息将成为一个字节数组,字节数组发送传输层。
 接收方:传输层接收字节数组,消息编码器并行化字节数组到一条消息,该方法及其参数并行化到一个SOAP消息,方法是被监听的。 当加入压缩信息编码器,该方法要求有一点改变:发送方:代码中加入方法,该方法及其参数的序列化成SOAP消息,消息契约编码让其内在的信息编码序列的信息成为一个字节数组,消息契约编码压缩的字节数组第二个字节数组,字节数组发送传输层。

     接收方:传输层接收字节数组,消息契约编码的字节数组解压到第二字节数组,消息契约编码让其内在的信息编码化的第二个字节数组消息,该方法及其参并行化到SOAP消息,方法是被监听的。
 
     这个消息契约编码分为几个类:

     CompactMessageEncoder //这个类提供了信息编码实施。

     CompactMessageEncoderFactory //这个类是负责提供契约信息编码实例。

     CompactMessageEncodingBindingElement //这个类负责通道的协议约束规范。
 
     CompactMessageEncodingElement //这个类使信息编码通过增加应用程序配置文件。
                 
                               图2 消息通道编码器静态类图 
 
     压缩方法:契约消息编码器是使用gzip压缩的NET Framework范围内执行的,是调用System.IO.Compression.GZipStream名字空间类中。

     加入引用CompactMessageEncoder.dll,修改app.config文件引用,应用程序必须要在客户端和服务器端。
压缩缓冲代码:
private   static  ArraySegment < byte >  CompressBuffer(ArraySegment < byte >  buffer, BufferManager bufferManager,  int  messageOffset)
        {
            
//  Create a memory stream for the final message
            MemoryStream memoryStream  =   new  MemoryStream();

            
//  Copy the bytes that should not be compressed into the stream
            memoryStream.Write(buffer.Array,  0 , messageOffset);

            
//  Compress the message into the stream
             using  (GZipStream gzStream  =   new  GZipStream(memoryStream, CompressionMode.Compress,  true ))
            {
                gzStream.Write(buffer.Array, messageOffset, buffer.Count);
            }

            
//  Convert the stream into a bytes array
             byte [] compressedBytes  =  memoryStream.ToArray();

            
//  Allocate a new buffer to hold the new bytes array
             byte [] bufferedBytes  =  bufferManager.TakeBuffer(compressedBytes.Length);

            
//  Copy the compressed data into the allocated buffer
            Array.Copy(compressedBytes,  0 , bufferedBytes,  0 , compressedBytes.Length);

             
//  Release the original buffer we got as an argument
            bufferManager.ReturnBuffer(buffer.Array);

            
//  Create a new ArraySegment that points to the new message buffer
            ArraySegment < byte >  byteArray  =   new  ArraySegment < byte > (bufferedBytes, messageOffset, compressedBytes.Length  -  messageOffset);

            
return  byteArray;
        }
解压缓冲代码:
Code
   
private   static  ArraySegment < byte >  DecompressBuffer(ArraySegment < byte >  buffer, BufferManager bufferManager)
        {
            
//  Create a new memory stream, and copy into it the buffer to decompress
            MemoryStream memoryStream  =   new  MemoryStream(buffer.Array, buffer.Offset, buffer.Count);

            
//  Create a memory stream to store the decompressed data
            MemoryStream decompressedStream  =   new  MemoryStream();

            
//  The totalRead stores the number of decompressed bytes
             int  totalRead  =   0 ;

            
int  blockSize  =   1024 ;

            
//  Allocate a temporary buffer to use with the decompression
             byte [] tempBuffer  =  bufferManager.TakeBuffer(blockSize);

            
//  Uncompress the compressed data
             using  (GZipStream gzStream  =   new  GZipStream(memoryStream, CompressionMode.Decompress))
            {
                
while  ( true )
                {
                    
//  Read from the compressed data stream
                     int  bytesRead  =  gzStream.Read(tempBuffer,  0 , blockSize);
                    
if  (bytesRead  ==   0 )
                        
break ;
                    
//  Write to the decompressed data stream
                    decompressedStream.Write(tempBuffer,  0 , bytesRead);
                    totalRead 
+=  bytesRead;
                }
            }
            
//  Release the temporary buffer
            bufferManager.ReturnBuffer(tempBuffer);

            
//  Convert the decompressed data stream into bytes array
             byte [] decompressedBytes  =  decompressedStream.ToArray();

            
//  Allocate a new buffer to store the message 
             byte [] bufferManagerBuffer  =  bufferManager.TakeBuffer(decompressedBytes.Length  +  buffer.Offset);

            
//  Copy the bytes that comes before the compressed message in the buffer argument
            Array.Copy(buffer.Array,  0 , bufferManagerBuffer,  0 , buffer.Offset);

            
//  Copy the decompressed data
            Array.Copy(decompressedBytes,  0 , bufferManagerBuffer, buffer.Offset, decompressedBytes.Length);

            
//  Create a new ArraySegment that points to the new message buffer
            ArraySegment < byte >  byteArray  =   new  ArraySegment < byte > (bufferManagerBuffer, buffer.Offset, decompressedBytes.Length);

            
//  Release the original message buffer
            bufferManager.ReturnBuffer(buffer.Array);

            
return  byteArray;
        }
改变服务端配置
    加入消息契约编码器之前 app.config 的实例:
<? xml version="1.0" encoding="utf-8"  ?>
< configuration >  
    
< system.serviceModel >  
        
< services >  
            
< service  name ="Server.MyService" >
                
< endpoint 
                    
address ="net.tcp://localhost:1234/MyService"  
                    binding
="netTcpBinding"
                    contract
="Server.IMyService"   />  
            
</ service >  
        
</ services >  
    
</ system.serviceModel >
</ configuration >
加入消息契约编码器后 app.config 的例子:
Code
<? xml version="1.0" encoding="utf-8"  ?>
< configuration >  
    
< system.serviceModel >  
        
< services >  
            
< service  name ="Server.MyService" >

            
<!--  Set the binding of the endpoint to customBinding  -->                  
            
< endpoint 
                    
address ="net.tcp://localhost:1234/MyService"  
                    binding
="customBinding"
                    contract
="Server.IMyService"   />  
            
</ service >  
        
</ services >  

        
<!--  Defines a new customBinding that contains the compactMessageEncoding  -->          
        
< bindings >  
            
< customBinding >  
                
< binding  name ="compactBinding" >  
                    
< compactMessageEncoding >

                
<!--  Defines the inner message encoder as binary encoder  -->                         
                
< binaryMessageEncoding  />  
                    
</ compactMessageEncoding >  
                    
< tcpTransport  />  
                
</ binding >  
            
</ customBinding >  
        
</ bindings >  

    
<!--  Adds the extension dll so the WCF can find the compactMessageEncoding  -->
        
< extensions >  
            
< bindingElementExtensions >  
                
< add  name ="compactMessageEncoding"  type ="Amib.WCF.CompactMessageEncodingElement, CompactMessageEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"   />
            
</ bindingElementExtensions >  
        
</ extensions >  

     
</ system.serviceModel >
</ configuration >
客户端配置变化
加入消息契约编码器之前 app.config 的实例:
Code
加入消息契约编码器后 app.config 的例子:
Code
  
这种压缩方法,消息堵塞的几率很小。 使用 CompactMessageEncoder 在同一台机器运行客户端和服务器上可能会降低效率。

 

本文转自 高阳 51CTO博客,原文链接:http://blog.51cto.com/xiaoyinnet/196083 ,如需转载请自行联系原作者

相关文章
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
王耀恒:从网络营销老兵到GEO技术布道者
在王耀恒看来,AI时代的技术竞争已从“信息不对称”转向“系统化应用能力”。他的GEO课程体系正是这一理念的体现——技术可以被复制,但深度实践验证的系统框架、认知升级路径和教学转化艺术却构成了难以逾越的壁垒。
|
1月前
|
机器学习/深度学习 人工智能 监控
上海拔俗AI软件定制:让技术真正为你所用,拔俗网络这样做
在上海,企业正通过AI软件定制破解通用化难题。该模式以业务场景为核心,量身打造智能解决方案,涵盖场景化模型开发、模块化架构设计与数据闭环优化三大技术维度,推动技术与业务深度融合,助力企业实现高效、可持续的数字化转型。
|
2月前
|
监控 前端开发 安全
Netty 高性能网络编程框架技术详解与实践指南
本文档全面介绍 Netty 高性能网络编程框架的核心概念、架构设计和实践应用。作为 Java 领域最优秀的 NIO 框架之一,Netty 提供了异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本文将深入探讨其 Reactor 模型、ChannelPipeline、编解码器、内存管理等核心机制,帮助开发者构建高性能的网络应用系统。
228 0
|
10月前
|
边缘计算 容灾 网络性能优化
算力流动的基石:边缘网络产品技术升级与实践探索
本文介绍了边缘网络产品技术的升级与实践探索,由阿里云专家分享。内容涵盖三大方面:1) 云编一体的混合组网方案,通过边缘节点实现广泛覆盖和高效连接;2) 基于边缘基础设施特点构建一网多态的边缘网络平台,提供多种业务形态的统一技术支持;3) 以软硬一体的边缘网关技术实现多类型业务网络平面统一,确保不同网络间的互联互通。边缘网络已实现全球覆盖、差异化连接及云边互联,支持即开即用和云网一体,满足各行业需求。
339 4
|
4月前
|
监控 算法 安全
基于 C# 基数树算法的网络屏幕监控敏感词检测技术研究
随着数字化办公和网络交互迅猛发展,网络屏幕监控成为信息安全的关键。基数树(Trie Tree)凭借高效的字符串处理能力,在敏感词检测中表现出色。结合C#语言,可构建高时效、高准确率的敏感词识别模块,提升网络安全防护能力。
132 2
|
6月前
|
机器学习/深度学习 算法 PyTorch
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
深度学习近年来在多个领域取得了显著进展,但其核心组件——人工神经元和反向传播算法自提出以来鲜有根本性突破。穿孔反向传播(Perforated Backpropagation)技术通过引入“树突”机制,模仿生物神经元的计算能力,实现了对传统神经元的增强。该技术利用基于协方差的损失函数训练树突节点,使其能够识别神经元分类中的异常模式,从而提升整体网络性能。实验表明,该方法不仅可提高模型精度(如BERT模型准确率提升3%-17%),还能实现高效模型压缩(参数减少44%而无性能损失)。这一革新为深度学习的基础构建模块带来了新的可能性,尤其适用于边缘设备和大规模模型优化场景。
306 16
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
|
6月前
|
调度 Python
探索Python高级并发与网络编程技术。
可以看出,Python的高级并发和网络编程极具挑战,却也饱含乐趣。探索这些技术,你将会发现:它们好比是Python世界的海洋,有穿越风暴的波涛,也有寂静深海的奇妙。开始旅途,探索无尽可能吧!
185 15
|
6月前
|
监控 算法 JavaScript
基于 JavaScript 图算法的局域网网络访问控制模型构建及局域网禁止上网软件的技术实现路径研究
本文探讨局域网网络访问控制软件的技术框架,将其核心功能映射为图论模型,通过节点与边表示终端设备及访问关系。以JavaScript实现DFS算法,模拟访问权限判断,优化动态策略更新与多层级访问控制。结合流量监控数据,提升网络安全响应能力,为企业自主研发提供理论支持,推动智能化演进,助力数字化管理。
180 4
|
7月前
|
存储 双11 数据中心
数据中心网络关键技术,技术发明一等奖!
近日,阿里云联合清华大学与中国移动申报的“性能可预期的大规模数据中心网络关键技术与应用”项目荣获中国电子学会技术发明一等奖。该项目通过端网融合架构,实现数据中心网络性能的可预期性,在带宽保障、时延控制和故障恢复速度上取得重大突破,显著提升服务质量。成果已应用于阿里云多项产品及重大社会活动中,如巴黎奥运会直播、“双十一”购物节等,展现出国际领先水平。

热门文章

最新文章