2009-08-15 11 views
16

Tengo una aplicación cliente-servidor, que se comunica usando WCF, y usa NetDataContractSerializer para serializar el gráfico de objetos.Serializar el mensaje WCF de forma binaria, y no como mensaje SOAP

Dado que se transfieren muchos datos entre el servidor y el cliente, intenté disminuir su tamaño ajustando el tamaño de los miembros de datos (por ejemplo, cambiado int a corto, largo a int, etc.).

Después de terminar la sintonización, descubrí que ¡la cantidad de datos transferidos no ha cambiado!
El problema es que NetDataContractSerializer serializa el gráfico de objetos en XML, así que no importa cuál sea el tamaño del miembro de datos, lo único que importa es el tamaño de su valor. Por ejemplo, el valor 10023 de un miembro de datos Int16 se serializará como la cadena "10023" (0x3130303233), en lugar de solo 10023 (0x2727).

Recuerdo que en Remoting podía usar BinaryFormatter que serializaba los valores de acuerdo con el tipo del miembro de datos, pero no sé si es posible usarlo con WCF.

¿Alguien tiene una solución?

Respuesta

35

WCF utiliza mensajes SOAP, pero qué tipo de codificación de mensajes se utiliza, es totalmente de usted.

Básicamente, de fábrica, tiene dos: codificación de texto (representación de texto de mensaje XML) o codificación binaria. Puede escribir su propia codificación de mensajes, si realmente debe y necesita hacerlo.

Fuera de la caja, los enlaces basicHttp y wsHttp usan codificación de texto, pero puede cambiar eso si lo desea. El enlace netTcp (que es la clara opción preferida detrás de los firewalls corporativos) usará binary de forma predeterminada.

También puede definir (justo en config) su propio protocolo "binario http", si lo desea:

<bindings> 
     <customBinding> 
     <binding name="BinaryHttpBinding"> 
      <binaryMessageEncoding /> 
      <httpTransport /> 
     </binding> 
     </customBinding> 
    </bindings> 

y luego utilizarlo en su servicio y lado del cliente config:

<services> 
     <service name="YourService"> 
     <endpoint 
      address="http://localhost:8888/YourService/" 
      binding="customBinding" 
      bindingConfiguration="BinaryHttpBinding" 
      contract="IYourService" 
      name="YourService" /> 
     </service> 
    </services> 

Ahora tiene un protocolo de transporte basado en http, que codificará su mensaje en formato binario compacto, ¡para que lo use y disfrute!

No necesita codificación adicional, ni hacks desordenados, ni mucho código de serialización manual XML. ¡Simplemente conéctelo y úselo! ¡Ah, la alegría de la flexibilidad de WCF!

+0

también lo hace el mensaje de codificación binaria ofrecen una mejora significativa del rendimiento? ¿Se reduce el tiempo de serialización o solo se reduce el tamaño del mensaje? –

+0

He utilizado este enlace personalizado así como binaryMessageEncoding con el transporte de canalización con nombre, y los mensajes siguen siendo codificación XML según los registros de mensajes en el detector de seguimiento así como WCF Test Client. No estoy 100% seguro de que estos no estén haciendo su propia serialización XML de los objetos para iniciar sesión en lugar de tomar el mensaje sin procesar. WCF hace que sea tan difícil conectarse a la solicitud/respuesta en bruto vs. WebAPI que lo hace más fácil. – AaronLS

+0

Esta respuesta es útil, pero tenga en cuenta que la codificación binaria solo cambia la forma en que se envía el mensaje "por cable", es decir, después de que se serializa. Si bien esto ciertamente reduce el tamaño de los datos, no cambia el método de serialización. La codificación binaria se puede usar con compresión para obtener mejores resultados. –

6

Primero pensé; ¿Ha habilitado la compresión de transporte?

¿Cuán complejos son los datos? Si es algo que funcionaría con el DataContractSerializer normal (es decir, un árbol de objetos simple), entonces protobuf-net puede ser útil. Es una biblioteca muy eficiente binario serialización con soporte para WCF a través de atributos adicionales en el contrato de servicios - por ejemplo:

[ServiceContract] 
public interface IFoo 
{ 
    [OperationContract, ProtoBehavior] 
    Test3 Bar(Test1 value); 
} 

(el [ProtoBehaviour] es lo intercambia en los diferentes serializador para este método)

Sin embargo:

  • tiene que ser capaz de identificar una etiqueta numérica para cada propiedad - ya sea a través de atributos adicionales, o puede utilizar el Order en un atributo [DataMember(Order = x)]
  • herencia (si lo está usando) requiere atributos adicionales
  • funciona mejor si está utilizando el intercambio de ensamblaje ("Mex" no le gusta que ...)

Muy bien, sino que también funciona con MTOM, reduciendo el costo de base-64 para mensajes más grandes.

1

El codificador binario NO serializará su objeto en binario, ¡ya que no tiene nada que ver con la serialización! Es algo que funciona en una capa inferior y decide cómo se transporta el mensaje entre el servidor y el cliente.

En otras palabras, el objeto primero será serializado (por DataContractSerializer, por ejemplo) y luego codificado (por BinaryEncoder). Por lo tanto, su objeto siempre estará en formato XML siempre que participe DataContractSerializer.

Si desea una información más compacto y mejor rendimiento, leer este blog:

https://blogs.msdn.microsoft.com/dmetzgar/2011/03/29/protocol-buffers-and-wcf/

1

Aquí es un ejemplo de cómo hacer de codificación personalizado aquí https://www.codeproject.com/Articles/434665/WCF-Serialization-A-Case-Study

Vale la pena señalar que lo que realmente se envía es lo mismo que si tuvieras un método de servicio enviando byte [] con codificación predeterminada. El mensaje que va por el cable sigue usando un sobre XML de SOAP, independientemente de cómo configure la serialización.

Se ve así:

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> 
Cuestiones relacionadas