zoukankan      html  css  js  c++  java
  • WCF use ProtoBuf

        ProtoBuf, 比起xml和json, 传输的数据里面没有自描述标签, 而且是基于二进制的, 所以有着超高的传输效率, 据牛人张善友的描述, 可以替代WCF的自带的编码方案, 效率有极大的提升.

        在网上搜罗了一遍, 很多博文都是复制张善友的文章, 有些细节没有说清楚, 所以将自己尝试的方法分享给大家.

        1. 在VS2013中新建一个 WCF服务库, 名字使用默认的WcfServiceLibrary1

        2. 在当前解决方案再新建一个Console程序, 名字叫Client

        3. 使用nuget安装proto-net, 为什么不用最新的 2.1.0 版本呢? 因为要弹出错误 protobuf-net”已拥有为“NETStandard.Library”定义的依赖项。我估计应该是转.Net Core了, 没有继续研究了, 先用 2.0.0.668 吧

    Install-Package protobuf-net -Version 2.0.0.668 -ProjectName WcfServiceLibrary1

    Install-Package protobuf-net -Version 2.0.0.668 -ProjectName Client

        将WcfServiceLibrary1packagesprotobuf-net.2.0.0.668lib et40protobuf-net.dll拷贝到

    WcfServiceLibrary1WcfServiceLibrary1

    WcfServiceLibrary1Client

        4. 在服务端注册 行为扩展: 将下面的代码拷贝到<system.serviceModel>下面, 注册行为扩展的时候要求protobuf-net.dll就放在项目文件夹, 这就是第3步拷贝的原因

        <extensions>
          <behaviorExtensions>
            <add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
          </behaviorExtensions>
        </extensions>

        5. 在服务端将 行为扩展 应用在 终结点行为 上: 在<behaviors>下面拷贝

          <endpointBehaviors>
            <behavior name="protoEndpointBehavior">
              <protobuf/>
            </behavior>
          </endpointBehaviors>

        6. 还有就是让服务使用这个终结点行为, 在 <endpoint> 下添加

    behaviorConfiguration="protoEndpointBehavior"

        App.config最终样子

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.web>
        <compilation debug="true" />
      </system.web>
      <system.serviceModel>
        <extensions>
          <behaviorExtensions>
            <add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
          </behaviorExtensions>
        </extensions>
        <services>
          <service name="WcfServiceLibrary1.Service1">
            <endpoint address="" behaviorConfiguration="protoEndpointBehavior"
              binding="basicHttpBinding" contract="WcfServiceLibrary1.IService1">
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/" />
              </baseAddresses>
            </host>
          </service>
        </services>
        <behaviors>
          <endpointBehaviors>
            <behavior name="protoEndpointBehavior">
              <protobuf/>
            </behavior>
          </endpointBehaviors>
          <serviceBehaviors>
            <behavior>
              <serviceMetadata httpGetEnabled="True"/>
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

        7. 配置文件写好了后, 还需要修改IServer.cs, 这里只是简单例子, 就将 CompositeType 作为例子, 需要添加ProtoContract、ProtoMember 两种特性, 这样protobuf-net的编码器才能正确识别

        [DataContract]
        [ProtoContract]
        public class CompositeType
        {
            bool boolValue = true;
            string stringValue = "Hello ";
    
            [DataMember]
            [ProtoMember(1)]
    
            public bool BoolValue
            {
                get { return boolValue; }
                set { boolValue = value; }
            }
    
            [DataMember]
            [ProtoMember(2)]
            public string StringValue
            {
                get { return stringValue; }
                set { stringValue = value; }
            }
        }
       8. public interface IService1 还要要添加 [ServiceContract] 特性

        

        9. 客户端引用WCF服务, 因为WCF服务就在本项目, 所以要选择 解决方案中的服务, 就命名为ServiceReference1吧

    image

       10. 客户端也要增加刚才的扩展和终结点行为, 这样客户端才能解析protobuf数据, 最终App.config 是这样的

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
          <extensions>
            <behaviorExtensions>
              <add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
            </behaviorExtensions>
          </extensions>
            <bindings>
                <basicHttpBinding>
                    <binding name="BasicHttpBinding_IService1" />
                </basicHttpBinding>
            </bindings>
            <client>
                <endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/"
                    behaviorConfiguration="protoEndpointBehavior" binding="basicHttpBinding"
                    bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
                    name="BasicHttpBinding_IService1" />
            </client>
          <behaviors>
            <endpointBehaviors>
              <behavior name="protoEndpointBehavior">
                <protobuf />
              </behavior>
            </endpointBehaviors>
          </behaviors>
        </system.serviceModel>
    </configuration>

        11. 将解决方案设置为双启动, 右键解决方案 -->  属性 --> 启动项目 --> 多启动项目    

    image

         11. 好了, 可以在客户端调用服务了

    static void Main(string[] args)
    {
        var proxy =new ServiceReference1.Service1Client();
        var result=proxy.GetDataUsingDataContract(new ServiceReference1.CompositeType(){ StringValue="test });
        Console.WriteLine(result.StringValue);
    }

    但是得到结果是null

    image

        12. 查看别人的博文 在Wcf中应用ProtoBuf替代默认的序列化器  , 原来protobuf 不是WCF的嫡出, 通过服务引用, 并不会像DataMember这种原生支持的Attribute那样, 把ProtoMember传输到Client的自动生成代码里, 所以还需要手工添加, 蛋疼啊

    image

        在打开的Reference.cs中找到属性 public bool BoolValue   添加  [ProtoMember(1)]

        找到属性 public string StringValue 添加  [ProtoMember(2)]
         这下终于有结果了

    image

         后记, protobuf 并不是为WCF准备的, 而是应该与 gRPC 配合使用, 在 gRPC 的示例文档中可以看到如将一个非常简单的 .proto文件编译成复杂的cs文件, 然后分别被服务端和客户端引用, 最终实现远程调用, 不过示例环境是VS2015

    源代码

  • 相关阅读:
    grunt in webstorm
    10+ Best Responsive HTML5 AngularJS Templates
    响应式布局
    responsive grid
    responsive layout
    js event bubble and capturing
    Understanding Service Types
    To add private variable to this Javascript literal object
    Centering HTML elements larger than their parents
    java5 新特性
  • 原文地址:https://www.cnblogs.com/zhouandke/p/5933351.html
Copyright © 2011-2022 走看看