以二进制方式序列化WCF消息,而不是SOAP消息

And*_*ndy 17 wcf serialization

我有一个客户端 - 服务器应用程序,它使用WCF进行通信,并使用NetDataContractSerializer序列化对象图.

由于在服务器和客户端之间传输了大量数据,我尝试通过微调数据成员的大小来减小其大小(例如,将int更改为short,将long更改为int等).

完成调整后,我发现传输的数据量没有变化!
问题是,NetDataContractSerializer将对象图序列化为XML,因此无论数据成员的大小如何,唯一重要的是其值的大小.例如,Int16数据成员的值10023将序列化为字符串"10023"(0x3130303233),而不是仅仅10023(0x2727).

我记得在Remoting中我可以使用BinaryFormatter根据数据成员的类型序列化值,但我不知道是否可以将它与WCF一起使用.

有人有解决方案吗?

mar*_*c_s 35

WCF使用SOAP消息,但使用什么样的消息编码完全取决于您.

基本上,开箱即用,你有两个:文本编码(XML消息的文本表示)或二进制编码.如果你真的必须要,你可以编写自己的消息编码.

开箱即用,basicHttp和wsHttp绑定使用文本编码 - 但如果你愿意,你可以改变它.netTcp绑定(这是企业防火墙背后的明确首选)将默认使用二进制.

如果您愿意,您还可以定义(仅在配置中)您自己的"二进制http"协议:

   <bindings>
      <customBinding>
        <binding name="BinaryHttpBinding">
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
Run Code Online (Sandbox Code Playgroud)

然后在您的服务和客户端配置中使用它:

   <services>
      <service name="YourService">
        <endpoint
          address="http://localhost:8888/YourService/"
          binding="customBinding"
          bindingConfiguration="BinaryHttpBinding"
          contract="IYourService"
          name="YourService" />
      </service>
    </services>
Run Code Online (Sandbox Code Playgroud)

现在你有一个基于http的传输协议,它将以紧凑的二进制编码你的消息,供你使用和享受!

不需要额外的编码或杂乱的黑客或大量的手动XML序列化代码 - 只需将它们连接在一起并使用即可!啊,WCF灵活的快乐!


Mar*_*ell 6

首先想到的; 你启用了传输压缩吗?

数据有多复杂?如果它适用于常规DataContractSerializer(即简单的对象树),那么protobuf-net可能是有用的.它是一个非常有效的二进制序列化库,通过服务契约上的附加属性支持WCF - 例如:

[ServiceContract]
public interface IFoo
{
    [OperationContract, ProtoBehavior]
    Test3 Bar(Test1 value);
}
Run Code Online (Sandbox Code Playgroud)

(这[ProtoBehaviour]是该方法的不同序列化器中的交换)

然而:

  • 它需要能够为每个属性标识一个数字标记 - 通过额外的属性,或者它可以使用Orderon [DataMember(Order = x)]属性
  • 继承(如果您使用它)需要额外的属性
  • 如果你使用汇编共享("mex"不喜欢它...)它最有效

很好,它也适用于MTOM,降低了较大消息的基本成本64.


小智 5

这是如何在此处进行自定义编码的示例https://www.codeproject.com/Articles/434665/WCF-Serialization-A-Case-Study

值得注意的是,实际发送的内容与使用默认编码发送 byte[] 的服务方法相同。无论您如何配置序列化,通过网络传输的消息仍然使用 SOAP XML 信封。

它看起来像这样:

POST http://127.0.0.1:12345/forSwerGup182948/Client HTTP/1.1
Content-Type: text/xml; charset=utf-8
VsDebuggerCausalityData: uIDPo+WkoDpet/JOtGlW+EHdpDQAAAAAvFs5XOJ0tEW0wTvNVRDUIiabR6u+p+JNnd5Z+SWl1NcACQAA
SOAPAction: "http://tempuri.org/ITransmissionService/SendData"
Host: 127.0.0.1:12345
Expect: 100-continue
Accept-Encoding: gzip, deflate
Content-Length: 2890

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><SendData xmlns="http://tempuri.org/"><message>eyI8Q2FsbGJhY2tJZD5rX19CYWNraW5nRmllbGQiOiJlYTQ3ZWIzMS1iYjIzLTRkODItODljNS1hNTZmNjdiYmQ4MTQiLCI8RnJvbT5rX19CYWNraW5nRmllbGQiOnsiPENoYW5uZWxOYW1lPmtfX0JhY2tpbmdGaWVsZCI6Ikdyb3VwMSIsIjxOYW1lPmtfX0==</message></SendData></s:Body></s:Envelope>
Run Code Online (Sandbox Code Playgroud)