Как убедиться, что WCF ChannelFactory использует настройки привязки в конфигурации xml (MaxArrayLength игнорируется) - PullRequest
6 голосов
/ 03 декабря 2009

Как убедиться, что WCF ChannelFactory использует настройки привязки в конфигурации xml (MaxArrayLength игнорируется)

Привет, я новичок в Wcf и пишу свой первый сервис и клиент Wcf. Я предпочитаю не использовать инструменты для генерации конфигурации; Я бы лучше написал конфиг сам. Проблема, которую я пытаюсь Чтобы решить, клиент общается с сервисом через NetTcp. Служба может потенциально возвращает очень большие полезные нагрузки (больше, чем по умолчанию readerQuotas.maxArrayLength). Компоненты, которые я изначально разработал, работают нормально, когда полезные данные потока байтов относительно низки (то есть меньше, чем значение по умолчанию, которое, по его мнению, составляет около 16 КБ). Я могу решить эту проблему программно, создав привязку и установив MaxArrayLength до достаточно большого значения. Тем не менее, я должен быть в состоянии выполнить эквивалент в конфигурация xml.

Мой app.config (клиент):

<?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>

Код для создания клиентского прокси выглядит следующим образом:

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 ...
}

Обратите внимание, что код связан с конфигурацией переменной 'endpointName'.

Конфигурация на стороне службы (я не думаю, что это актуально, но включена для полноты):

<?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>

Когда я запускаю клиента в сценарии, в котором служба возвращает большой поток байтов, выдается исключение, и сообщение внутри исключения:

Произошла ошибка связи: соединение с сокетом было прервано. Это может быть вызвано из-за ошибки обработки вашего сообщения или превышения времени ожидания удаленным хостом, или основная проблема сетевого ресурса. Тайм-аут локального сокета был '00: 00: 59.9687494 '

(Это не тайм-аут, так как ошибка возникает немедленно.)

Как уже говорилось ранее, я могу исправить это программно следующим образом:

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

return new ChannelFactory<IRemoteDataRequester>(binding);

это работает нормально, но мне нужно сделать это через config для тестирования.

Я также пробовал следующее:

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

Но это не имеет значения.

Итак, мой вопрос: почему, когда я создаю канал из конфигурации конечной точки, которая включает в себя привязку с MaxArrayLength установлен в подходящее значение, это значение игнорируется?

С уважением.

Хорошо, я нашел решение. Конфигурация работала все время. Однако предоставленная мною конфигурация («unsecureNetTcpBinding»), которую я нашел в примере кода, иллюстрирующем http-сервисы (не net tcp-сервис, который я разрабатываю) Мошеннический кусок конфига был 'security mode = "None"' Когда я вынул это, это сработало. Если я изменяю readerQuotas maxArrayLength, это применяется по мере необходимости. Причина, по которой мой код работал, заключается в том, что я не устанавливал режим безопасности ни на один. Спасибо за ваши комментарии и помощь.

Ответы [ 2 ]

1 голос
/ 03 декабря 2009

Я думаю, что проблема может заключаться в том, что в конфиге ваш номер имеет только 6 нулей, а в коде у вас 7 нулей. Может быть?

0 голосов
/ 03 декабря 2009

Возможно, MaxArrayLength не подходит для установки.

Попробуйте "maxBufferSize" и "MaxBufferPoolSize":

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

Но реальный вопрос: если у вас большие объемы данных, почему вы не используете потоковую передачу WCF ?? Это именно то, для чего он предназначен.

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

Размеры maxBufferSize и т. Д. Специально установлены на довольно маленькое значение - чтобы избежать атак отказа в обслуживании. Простое включение этих уровней до уровня MaxInt делает ваш сервер уязвимым для этих атак DOS.

UPDATE:
Попробуйте сделать это: - создать новое консольное приложение - добавить ссылки на System.Runtime.Serialization и System.ServiceModel - добавьте app.config, который содержит именно то, что содержит ваш клиентский конфиг - поместите эти строки кода в консольное приложение:

   class Program
   {
        static void Main(string[] args)
        {
            NetTcpBinding binding = new NetTcpBinding("unsecureNetTcpBinding");
            int maxArrayLength = binding.ReaderQuotas.MaxArrayLength;
            long maxReceivedMessageSize = binding.MaxReceivedMessageSize;
        }
    }
  • запустить и отладить - какие значения вы получаете ?? Я получаю именно то, что вы ввели: «1000000» для binding.ReaderQuotas.MaxArrayLength, «2147483647» для привязки. MaxReceivedMessageSize.

WCF распознает и использует эти настройки из конфигурации - 120% гарантировано. В вашем приложении должно быть что-то подозрительное .....

...