WCF消息压缩

WCF音讯压缩,wcf音信

对于WCF应用来讲,传输前减少恳求音讯和大张旗鼓信息,不但能够下落互联网流量,也能够抓好互连网传输的特性

后生可畏、音信压缩方案
二、用于数据压缩与解压缩组件
三、用于音信压缩与解压的零件
四、用于对伏乞/回复音讯压缩和平解决压缩的机件
五、将CompressionMessageFormatter用于WCF运营时框架的操作行为
六、查看结构压缩后的音讯
七、扩展

 

风华正茂、新闻压缩方案
  消息压缩在WCF中的实现其实一点也不细略,大家只须求在音信(乞求新闻/回复新闻卡塔 尔(阿拉伯语:قطر‎被体系化之后,发送从前实行压缩;在接受之后,反类别化从前开展解压缩就能够。针对压缩/解压缩使用的机遇,有三种标准的解决方案。通过自定义MessageEncoder和MessageEncodingBindingElement 来成功。

1.将编码后的字节流压缩传输

2.创立用于压缩和解压缩的信道

  1. 自定义MessageFormatter实现系列化后的回退和法类别化前的解压缩

这里要介绍的施工方案3。  

二、用于数据压缩与解压缩组件
  大家支撑两种格局的减少,Dflate和GZip。三种分裂的压缩算法通过如下概念的CompressionAlgorithm枚举表示。

1     public enum CompressionAlgorithm
2     {
3         GZip,
4         Deflate
5     }

而正如概念的DataCompressor负担依照上述二种压缩算法实际上的裁减少利和平解决压缩专门的学业。

 1     internal class DataCompressor
 2     {
 3         public static byte[] Compress(byte[] decompressedData, CompressionAlgorithm algorithm)
 4         {
 5             using (MemoryStream stream = new MemoryStream())
 6             {
 7                 if (algorithm == CompressionAlgorithm.Deflate)
 8                 {
 9                     GZipStream stream2 = new GZipStream(stream, CompressionMode.Compress, true);
10                     stream2.Write(decompressedData, 0, decompressedData.Length);
11                     stream2.Close();
12                 }
13                 else
14                 {
15                     DeflateStream stream3 = new DeflateStream(stream, CompressionMode.Compress, true);
16                     stream3.Write(decompressedData, 0, decompressedData.Length);
17                     stream3.Close();
18                 }
19                 return stream.ToArray();
20             }
21         }
22 
23         public static byte[] Decompress(byte[] compressedData, CompressionAlgorithm algorithm)
24         {
25             using (MemoryStream stream = new MemoryStream(compressedData))
26             {
27                 if (algorithm == CompressionAlgorithm.Deflate)
28                 {
29                     using (GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress))
30                     {
31                         return LoadToBuffer(stream2);
32                     }
33                 }
34                 else
35                 {
36                     using (DeflateStream stream3 = new DeflateStream(stream, CompressionMode.Decompress))
37                     {
38                         return LoadToBuffer(stream3);
39                     }
40                 }
41             }
42         }
43 
44         private static byte[] LoadToBuffer(Stream stream)
45         {
46             using (MemoryStream stream2 = new MemoryStream())
47             {
48                 int num;
49                 byte[] buffer = new byte[0x400];
50                 while ((num = stream.Read(buffer, 0, buffer.Length)) > 0)
51                 {
52                     stream2.Write(buffer, 0, num);
53                 }
54                 return stream2.ToArray();
55             }
56         }
57     }

三、用于新闻压缩与解压的机件  

  而针对消息的回降和解压缩通过如下一个MessageCompressor来产生。具体来说,我们透过上边定义的DataCompressor对消息的侧珍视部分剧情开展压缩,并将滑坡后的原委寄放到一个预订义的XML成分中(名称和命名空间分别为CompressedBody和

实际的落到实处如下:

 1     public class MessageCompressor
 2     {
 3         public MessageCompressor(CompressionAlgorithm algorithm)
 4         {
 5             this.Algorithm = algorithm;
 6         }
 7         public Message CompressMessage(Message sourceMessage)
 8         {
 9             byte[] buffer;
10             using (XmlDictionaryReader reader1 = sourceMessage.GetReaderAtBodyContents())
11             {
12                 buffer = Encoding.UTF8.GetBytes(reader1.ReadOuterXml());
13             }
14             if (buffer.Length == 0)
15             {
16                 Message emptyMessage = Message.CreateMessage(sourceMessage.Version, (string)null);
17                 sourceMessage.Headers.CopyHeadersFrom(sourceMessage);
18                 sourceMessage.Properties.CopyProperties(sourceMessage.Properties);
19                 emptyMessage.Close();
20                 return emptyMessage;
21             }
22             byte[] compressedData = DataCompressor.Compress(buffer, this.Algorithm);
23             string copressedBody = CompressionUtil.CreateCompressedBody(compressedData);
24             XmlTextReader reader = new XmlTextReader(new StringReader(copressedBody), new NameTable());
25             Message message2 = Message.CreateMessage(sourceMessage.Version, null, (XmlReader)reader);
26             message2.Headers.CopyHeadersFrom(sourceMessage);
27             message2.Properties.CopyProperties(sourceMessage.Properties);
28             message2.AddCompressionHeader(this.Algorithm);
29             sourceMessage.Close();
30             return message2;
31         }
32 
33         public Message DecompressMessage(Message sourceMessage)
34         {
35             if (!sourceMessage.IsCompressed())
36             {
37                 return sourceMessage;
38             }
39             CompressionAlgorithm algorithm = sourceMessage.GetCompressionAlgorithm();
40             sourceMessage.RemoveCompressionHeader();
41             byte[] compressedBody = sourceMessage.GetCompressedBody();
42             byte[] decompressedBody = DataCompressor.Decompress(compressedBody, algorithm);
43             string newMessageXml = Encoding.UTF8.GetString(decompressedBody);
44             XmlTextReader reader2 = new XmlTextReader(new StringReader(newMessageXml));
45             Message newMessage = Message.CreateMessage(sourceMessage.Version, null, reader2);
46             newMessage.Headers.CopyHeadersFrom(sourceMessage);
47             newMessage.Properties.CopyProperties(sourceMessage.Properties);
48             return newMessage;
49         }
50         public CompressionAlgorithm Algorithm { get; private set; }
51     }

上面是本着Message类型而定义了生龙活虎部分恢弘方法和增派方法。

 1     public static class CompressionUtil
 2     {
 3         public const string CompressionMessageHeader = "Compression";
 4         public const string CompressionMessageBody = "CompressedBody";
 5         public const string Namespace = "http://www.yswenli.net/compression";
 6 
 7         public static bool IsCompressed(this Message message)
 8         {
 9             return message.Headers.FindHeader(CompressionMessageHeader, Namespace) > -1;
10         }
11 
12         public static void AddCompressionHeader(this Message message, CompressionAlgorithm algorithm)
13         {
14             message.Headers.Add(MessageHeader.CreateHeader(CompressionMessageHeader, Namespace, string.Format("algorithm = "{0}"", algorithm)));
15         }
16 
17         public static void RemoveCompressionHeader(this Message message)
18         {
19             message.Headers.RemoveAll(CompressionMessageHeader, Namespace);
20         }
21 
22         public static CompressionAlgorithm GetCompressionAlgorithm(this Message message)
23         {
24             if (message.IsCompressed())
25             {
26                 var algorithm = message.Headers.GetHeader<string>(CompressionMessageHeader, Namespace);
27                 algorithm = algorithm.Replace("algorithm =", string.Empty).Replace(""", string.Empty).Trim();
28                 if (algorithm == CompressionAlgorithm.Deflate.ToString())
29                 {
30                     return CompressionAlgorithm.Deflate;
31                 }
32 
33                 if (algorithm == CompressionAlgorithm.GZip.ToString())
34                 {
35                     return CompressionAlgorithm.GZip;
36                 }
37                 throw new InvalidOperationException("Invalid compression algrorithm!");
38             }
39             throw new InvalidOperationException("Message is not compressed!");
40         }
41 
42         public static byte[] GetCompressedBody(this Message message)
43         {
44             byte[] buffer;
45             using (XmlReader reader1 = message.GetReaderAtBodyContents())
46             {
47                 buffer = Convert.FromBase64String(reader1.ReadElementString(CompressionMessageBody, Namespace));
48             }
49             return buffer;
50         }
51 
52         public static string CreateCompressedBody(byte[] content)
53         {
54             StringWriter output = new StringWriter();
55             using (XmlWriter writer2 = XmlWriter.Create(output))
56             {
57                 writer2.WriteStartElement(CompressionMessageBody, Namespace);
58                 writer2.WriteBase64(content, 0, content.Length);
59                 writer2.WriteEndElement();
60             }
61             return output.ToString();
62         }
63     }

四、用于对央求/回复消息压缩和解压缩的构件  

  音信的种类化和反连串化最后是经过MessageFormatter来成功的。具体来讲,顾客端通过ClientMessageFormatter完毕对乞求新闻的种类化和对还原新闻的种类化,而服务端通过DispatchMessageFormatter实现对诉求音信的反体系化和对恢复生机新闻的类别化。

  在暗许的动静下,WCF选取的MessageFormatter为DataContractSerializerOperationFormatter,它应用DataContractSerializer实行实际的种类化和法种类化操作。我们自定义的MessageFormatter实际上是对DataContractSerializerOperationFormatter的包裹,大家仍旧选取它来成功系列化和反类别化事业,额外完毕种类化后的压缩和法连串化前的解压缩。

  因为DataContractSerializerOperationFormatter是二个internal类型,大家唯有由此反射的措施来创设它。如下的代码片断为用于开展消息压缩与解压缩的自定义MessageFormatter,即CompressionMessageFormatter的定义。

 1     public class CompressionMessageFormatter : IDispatchMessageFormatter, IClientMessageFormatter
 2     {
 3         private const string DataContractSerializerOperationFormatterTypeName = "System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
 4 
 5         public IDispatchMessageFormatter InnerDispatchMessageFormatter { get; private set; }
 6         public IClientMessageFormatter InnerClientMessageFormatter { get; private set; }
 7         public MessageCompressor MessageCompressor { get; private set; }
 8 
 9         public CompressionMessageFormatter(CompressionAlgorithm algorithm, OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory)
10         {
11             this.MessageCompressor = new MessageCompressor(algorithm);
12             Type innerFormatterType = Type.GetType(DataContractSerializerOperationFormatterTypeName);
13             var innerFormatter = Activator.CreateInstance(innerFormatterType, description, dataContractFormatAttribute, serializerFactory);
14             this.InnerClientMessageFormatter = innerFormatter as IClientMessageFormatter;
15             this.InnerDispatchMessageFormatter = innerFormatter as IDispatchMessageFormatter;
16         }
17 
18         public void DeserializeRequest(Message message, object[] parameters)
19         {
20             message = this.MessageCompressor.DecompressMessage(message);
21             this.InnerDispatchMessageFormatter.DeserializeRequest(message, parameters);
22         }
23 
24         public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
25         {
26             var message = this.InnerDispatchMessageFormatter.SerializeReply(messageVersion, parameters, result);
27             return this.MessageCompressor.CompressMessage(message);
28         }
29 
30         public object DeserializeReply(Message message, object[] parameters)
31         {
32             message = this.MessageCompressor.DecompressMessage(message);
33             return this.InnerClientMessageFormatter.DeserializeReply(message, parameters);
34         }
35 
36         public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
37         {
38             var message = this.InnerClientMessageFormatter.SerializeRequest(messageVersion, parameters);
39             return this.MessageCompressor.CompressMessage(message);
40         }
41     }

 

五、将CompressionMessageFormatter用于WCF运转时框架的操作行为  

  ClientMessageFormatter和DispatchMessageFormatter实际上归于ClientOperation和DispatchOperation的组件。我们可以透过如下贰个自定义的操作行为CompressionOperationBehaviorAttribute将其应用到相应的操作上。

 1     [AttributeUsage(AttributeTargets.Method)]
 2     public class CompressionOperationBehaviorAttribute : Attribute, IOperationBehavior
 3     {
 4         public CompressionAlgorithm Algorithm { get; set; }
 5 
 6         public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { }
 7 
 8         public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
 9         {
10             clientOperation.SerializeRequest = true;
11             clientOperation.DeserializeReply = true;
12             var dataContractFormatAttribute = operationDescription.SyncMethod.GetCustomAttributes(typeof(DataContractFormatAttribute), true).FirstOrDefault() as DataContractFormatAttribute;
13             if (null == dataContractFormatAttribute)
14             {
15                 dataContractFormatAttribute = new DataContractFormatAttribute();
16             }
17 
18             var dataContractSerializerOperationBehavior = operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
19             clientOperation.Formatter = new CompressionMessageFormatter(this.Algorithm, operationDescription, dataContractFormatAttribute, dataContractSerializerOperationBehavior);
20         }
21 
22         public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
23         {
24             dispatchOperation.SerializeReply = true;
25             dispatchOperation.DeserializeRequest = true;
26             var dataContractFormatAttribute = operationDescription.SyncMethod.GetCustomAttributes(typeof(DataContractFormatAttribute), true).FirstOrDefault() as DataContractFormatAttribute;
27             if (null == dataContractFormatAttribute)
28             {
29                 dataContractFormatAttribute = new DataContractFormatAttribute();
30             }
31             var dataContractSerializerOperationBehavior = operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
32             dispatchOperation.Formatter = new CompressionMessageFormatter(this.Algorithm, operationDescription, dataContractFormatAttribute, dataContractSerializerOperationBehavior);
33         }
34 
35         public void Validate(OperationDescription operationDescription) { }
36     }

六、查看结构压缩后的音讯
为了表达应用了CompressionOperationBehaviorAttribute性子的操作方法对应的新闻是还是不是因此了压缩,大家得以经过三个简短的事例来检查。大家使用常用的酌量服务的例子,上面是服务合同和服务类型的定义。大家地点定义的CompressionOperationBehaviorAttribute应用到服务左券的Add操作上。

 1     [ServiceContract(Namespace = "http://www.yswenli.net/")]
 2     public interface ICalculator
 3     {
 4         [OperationContract]
 5         [CompressionOperationBehavior]
 6         double Add(double x, double y);
 7     }
 8     public class CalculatorService : ICalculator
 9     {
10         public double Add(double x, double y)
11         {
12             return x + y;
13         }
14     }

笔者们利用BasicHttpBinding作为终结点的绑定类型(具体的配置请查看源代码卡塔尔,上面是因此Fiddler获取的音信的情节,它们的主导部分都因此了基于压缩的编码。

1     <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
2       <s:Header>
3         <Compression xmlns="http://www.yswenli.net/compression">algorithm = "GZip"</Compression>
4       </s:Header>
5       <s:Body>
6         <CompressedBody xmlns="http://www.yswenli.net/compression">7L0HYBx ... CQAA//8=</CompressedBody>
7       </s:Body>
8     </s:Envelope>

重振旗鼓音信

1     <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
2       <s:Header>
3         <Compression xmlns="http://www.yswenli.net/compression">algorithm = "GZip"</Compression>
4       </s:Header>
5       <s:Body>
6         <CompressedBody xmlns="http://www.yswenli.net/compression">7L0H...PAAAA//8=</CompressedBody>
7       </s:Body>
8     </s:Envelope>

七、扩展

要是不想使微软自带的类别化或许因为有些原因(emoji字符十分等卡塔 尔(英语:State of Qatar)能够动用自定义的IDispatchMessageInspector。由于CompressionMessageFormatter使用基于DataContractSerializer类别化器的DataContractSerializerOperationFormatter实行音信的系列化和发种类化工作,而DataContractSerializer仅仅是WCF用于类别化的生机勃勃种暗许的取舍(WCF还足以应用守旧的XmlSeriaizer卡塔尔国;为了让CompressionMessageFormatter能够运用此外种类化器,能够对此开展对应的改良。

 

 

转载请标明本文来源:http://www.cnblogs.com/yswenli/p/6670081.html
更多内容欢迎我的的github:https://github.com/yswenli
如果发现本文有什么问题和任何建议,也随时欢迎交流~


 

对于WCF应用来讲,传输前减少要求音信和还原新闻,不但能够减低互连网流量,也足以增加网络传输的性质 风流倜傥、音信压...

本文由华夏彩票发布于计算机网络,转载请注明出处:WCF消息压缩

您可能还会对下面的文章感兴趣: