• 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

    源代码

  • 相关阅读:
    ROC-RK3308-CC 四核64位AIOT主板
    ROC-RK3399-PC六核64位高性能主板
    【新品发布】AIO-3399C六核高性能主板
    Firefly Mutil-Boot多系统安装启动程序发布
    excel快捷键
    word去格式按钮
    mongodb安装
    eclipse maven
    ubuntu win7引导修复
    maven(入门一)
  • 原文地址:https://www.cnblogs.com/zhouandke/p/5933351.html
Copyright © 2020-2023  润新知