2009-12-03 24 views
6

¿Cómo garantizar que el WCF ChannelFactory utiliza los valores de encuadernación en la configuración XML (MaxArrayLength se ignora)¿Cómo garantizar que el WCF ChannelFactory utiliza los valores de encuadernación en la configuración XML (MaxArrayLength se ignora)

Hola, soy nuevo en WCF y y escribiendo mi primer servicio y cliente de Wcf. Prefiero no usar las herramientas para generar config; Preferiría escribir la configuración yo mismo. El problema que intento resolver es el de un cliente que se comunica con un servicio a través de netTcp. El servicio puede devolver potencialmente cargas útiles muy grandes (más grandes que el predeterminado readerQuotas.maxArrayLength). Los componentes que he desarrollado inicialmente funcionan bien cuando las cargas útiles del flujo de bytes son relativamente bajas (es decir, menos del valor predeterminado, que se estima en unos 16K). Puedo resolver este problema programáticamente creando un enlace y estableciendo MaxArrayLength a un valor suficientemente grande. Sin embargo, necesito poder realizar el equivalente en la configuración xml.

Mi app.config (cliente) es:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 

     <client> 
      <endpoint address="net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService/" 
       binding="netTcpBinding" bindingConfiguration="unsecureNetTcpBinding" 
       contract="WcfDataServiceLib.IRemoteDataRequester" 
       name="DataRequesterEndpoint" /> 
     </client> 

     <bindings> 
      <netTcpBinding> 
       <binding name="unsecureNetTcpBinding" maxReceivedMessageSize="2147483647"> 
        <readerQuotas maxArrayLength="1000000" /> 
        <security mode="None" /> 
       </binding> 
      </netTcpBinding> 
     </bindings> 

    </system.serviceModel> 
</configuration> 

El código para crear el proxy de cliente es el siguiente:

private void Init() 
{ 
    var address = new EndpointAddress(@"net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService/"); 
    const string endpointName = "DataRequesterEndpoint"; 

    ChannelFactory<IRemoteDataRequester> factory = new ChannelFactory<IRemoteDataRequester>(
     endpointName); 

    IRemoteDataRequester proxy = factory.CreateChannel(address); 

    // call business methods on proxy ... 
} 

Tenga en cuenta que el código está vinculado a la configuración de la variable 'endpointName'.

config lado de servicio (no creo que esto es relevante, pero incluyó esté completo):

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 
     <services> 
      <service name="WcfDataServiceLib.RemoteDataRequesterService" behaviorConfiguration="WcfDataServiceLib.RemoteDataRequesterServiceBehavior"> 
       <host> 
        <baseAddresses> 
         <add baseAddress = "net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService" /> 
         <add baseAddress="http://localhost:8731/Design_Time_Addresses/WcfDataService/RemoteDataRequesterService/"/> 
        </baseAddresses> 
       </host> 
       <endpoint address ="" binding="netTcpBinding" bindingConfiguration="netTcpBindingConfig" contract="WcfDataServiceLib.IRemoteDataRequester"> 
        <identity> 
         <dns value="localhost"/> 
        </identity> 
       </endpoint> 
       <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 

      </service> 
     </services> 
     <behaviors> 
      <serviceBehaviors> 
       <behavior name="WcfDataServiceLib.RemoteDataRequesterServiceBehavior"> 
        <serviceMetadata httpGetEnabled="False"/> 
        <serviceDebug includeExceptionDetailInFaults="True" /> 
       </behavior> 
      </serviceBehaviors> 
     </behaviors> 

     <bindings> 
      <netTcpBinding> 
       <binding name="netTcpBindingConfig" receiveTimeout="00:00:30"> 
        <readerQuotas maxArrayLength="1000000"/> 
       </binding> 
       <binding name="netTcpReliableSession" receiveTimeout="00:00:30" > 
        <reliableSession enabled="true"/> 
       </binding> 
      </netTcpBinding> 
     </bindings> 

    </system.serviceModel> 
</configuration> 

Cuando ejecuto el cliente en un escenario en el que un gran flujo de bytes es devuelto por el servicio, se emite una excepción y el mensaje dentro de la excepción es:

Se produjo un error de comunicación: Se anuló la conexión del socket. Esto podría deberse a por un error procesando su mensaje o un tiempo de espera de recepción excedido por el host remoto, o un problema de recursos de red subyacente. tiempo de espera de socket local era '00: 00: 59.9687494'

(Esto no es un tiempo de espera que se produzca el error inmediatamente.)

Como se dijo anteriormente, que puede solucionar este problema mediante programación de la siguiente manera:

var binding = new NetTcpBinding 
{ 
    ReaderQuotas = { MaxArrayLength = 10000000 } 
}; 

return new ChannelFactory<IRemoteDataRequester>(binding); 

esto funciona bien, pero tengo que hacerlo a través de config para fines de prueba.

También he intentado el siguiente:

var binding = new NetTcpBinding("unsecureNetTcpBinding"); 
return new ChannelFactory<IRemoteDataRequester>(binding); 

Pero esto no hace ninguna diferencia.

Así que mi pregunta es por qué, cuando creo el canal de la configuración del punto final que incluye un enlace con MaxArrayLength establecido en un valor adecuado, ¿se ignora este valor?

Muchos saludos.

Ok, he encontrado la solución. La configuración estuvo funcionando todo el tiempo.Sin embargo, la configuración que proporcioné ("unsecureNetTcpBinding") que encontré en un ejemplo de código que ilustra los servicios http (no el servicio net tcp que es lo que estoy diseñando). La pieza de configuración incorrecta fue 'modo de seguridad = "Ninguna"' Cuando lo saqué, funcionó. Si cambio readerQuotas maxArrayLength, esto se aplica según lo requiera. La razón por la que mi código funcionó es porque no estaba configurando el modo de seguridad en ninguno. Gracias por sus comentarios y asistencia.

Respuesta

1

Creo que el problema podría ser que en la configuración su número solo tiene 6 ceros, mientras que en el código tiene 7 ceros. ¿Tal vez?

0

Tal vez MaxArrayLength no es la propiedad adecuada para configurar.

Try "MaxBufferSize" y "MaxBufferPoolSize":

<bindings> 
     <netTcpBinding> 
      <binding name="unsecureNetTcpBinding" 
        maxBufferSize="2147483647" 
        maxBufferPoolSize="2147483647" 
        maxReceivedMessageSize="2147483647"> 
       <readerQuotas maxArrayLength="1000000" /> 
       <security mode="None" /> 
      </binding> 
     </netTcpBinding> 
    </bindings> 

Pero la verdadera pregunta es: si usted tiene grandes cantidades de datos, por qué no estás haciendo uso de WCF streaming ?? Para eso está diseñado exactamente.

http://www.haveyougotwoods.com/archive/2008/04/14/wcf-message-streaming.aspx

El MaxBufferSize etc. tamaños se establecen en un valor bastante pequeño a propósito - para evitar ataques de denegación de servicio. El solo hecho de poner esos niveles hasta MaxInt hace que su servidor sea vulnerable a estos ataques DOS.

ACTUALIZACIÓN:
trate de hacer esto: - crear una nueva aplicación de consola - agregar referencias a System.Runtime.Serialization y System.ServiceModel - agregar un app.config que contiene exactamente lo que su configuración de cliente contiene - poner estas líneas del código de la aplicación de consola:

class Program 
    { 
     static void Main(string[] args) 
     { 
      NetTcpBinding binding = new NetTcpBinding("unsecureNetTcpBinding"); 
      int maxArrayLength = binding.ReaderQuotas.MaxArrayLength; 
      long maxReceivedMessageSize = binding.MaxReceivedMessageSize; 
     } 
    } 
  • ejecutar y depurar - qué valores se puede conseguir ?? Obtengo exactamente lo que ha introducido: "1000000" para binding.ReaderQuotas.MaxArrayLength, "2147483647" para binding.MaxReceivedMessageSize.

WCF reconoce y usa esas configuraciones desde config - 120% garantizado. Debe haber algo sospechoso sucediendo en su aplicación .....

+0

He intentado establecer maxBufferSize, maxBufferPoolSize y maxReceivedMessageSize, pero estos tampoco funcionan a través de la configuración. Solo para reiterar, puedo solucionar este problema a través de un código con maxArrayLength, pero quiero saber cómo hacerlo a través de config, cheers – Zephilim

+0

Estoy configurando maxBufferSize y MaxArrayLength en la configuración - no hay problema. Debe haber algo más sucediendo en su caso ..... –

Cuestiones relacionadas