Слишком большое сообщение при обмене данными WCF

#c# #wcf #nettcpbinding

#c# #wcf #nettcpbinding

Вопрос:

У меня есть служба Windows и приложение winform, которые обмениваются данными друг с другом с помощью WCF через TCP.

Иногда мне приходится обмениваться огромными данными, и я столкнулся с a CommunicationException на клиенте. Теперь мне трудно найти, какое свойство изменить и где (на стороне сервера или на стороне клиента?).

Проблема возникает, когда сервер возвращает клиенту значение, которое является 2-uple (моей собственной реализацией) из двух массивов double: Tuple<Double[], Double[]> (оба массива всегда имеют одинаковую длину).
Я заметил, что нет ошибки, когда массивы имеют длину 22 000 , но CommunicationException выдается, когда массивы имеют длину 44 000 .

Вот мой App.config файл, касающийся netTcpBinding части:

  • На сервере:
 <netTcpBinding>
    <binding name="MyBindingConf"
             maxReceivedMessageSize="5000000"
             sendTimeout="00:05:00">
        <readerQuotas maxArrayLength="67108864"
                      maxStringContentLength="67108864"/>
        <security mode="None" />
    </binding>
</netTcpBinding>
 
  • На клиенте:
 <netTcpBinding>
    <binding name="MyBindingConf"
             maxReceivedMessageSize="5000000"
             sendTimeout="00:59:00">
        <readerQuotas maxArrayLength="67108864"
                      maxStringContentLength="67108864"/>
        <security mode="None" />
    </binding>
</netTcpBinding>
 

Не могли бы вы указать, какое свойство изменить и с какой стороны?

P.S: Это не проблема с таймаутом.


Редактировать

Теперь у меня одинаковая nettcpbinding конфигурация как на сервере, так и на клиенте:

 <bindings>
    <netTcpBinding>
        <binding name="MyBindingConf" 
                 maxReceivedMessageSize="2147483647" 
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 sendTimeout="00:30:00">
            <readerQuotas maxDepth="32" 
                          maxStringContentLength="2147483647" 
                          maxArrayLength="2147483647" 
                          maxBytesPerRead="4096" 
                          maxNameTableCharCount="16384" />
            <security mode="None" />
        </binding>
    </netTcpBinding>
</bindings>
 

И то же самое serviceBehavior :

 <behaviors>
    <serviceBehaviors>
        <behavior name="Debug">
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
    </serviceBehaviors>
</behaviors>
 

Затем я получаю a NetDispatcherFaultException на клиенте, советуя мне увеличить maxArrayLength или maxItemsInObjectGraph . Но для меня эти значения уже в значительной степени установлены для того, что мне нужно передать, а также установлены на максимальные значения!

Вот InnerException сообщение:

При чтении XML-данных была превышена квота максимальной длины массива (19502) или квота максимального количества элементов в графе объектов. Эти квоты могут быть увеличены путем изменения свойства MaxArrayLength в XmlDictionaryReaderQuotas или параметра MaxItemsInObjectGraph.

Есть какие-нибудь подсказки? Откуда взялась эта 19 502 цифра?

Комментарии:

1. У вас есть свой <readerQuotas/>, установленный как на стороне клиента, так и на стороне сервера?

2. @ChrisNel52: Я обновил Q, в обоих случаях.

3. @Otiel — Ссылаетесь ли вы на привязки, которые вы настроили в своей конечной точке, с атрибутом bindingConfiguration? Если это не так, вы получите значения по умолчанию для привязки, а не те, которые вы установили и ожидали.

4. @Tim: Да, я : <endpoint binding="netTcpBinding" bindingConfiguration="MyBindingConf" contract="blah blah" name="blah blah" />

5. @Otiel Это снова открытый вопрос? с щедростью? если да, то в чем ваша новая проблема сейчас 🙂

Ответ №1:

Как на сервере, так и на клиенте вы должны настроить атрибут вашей привязки, если вы обмениваетесь большими объемами данных между ними. Например:

 <binding name="LargeSettings" maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00">
      <readerQuotas maxDepth="32" maxStringContentLength="200000000" maxArrayLength="200000000" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None" />
    </binding>
 

Пройдите свой путь от больших значений, чтобы найти то, которое вам подходит.

Редактировать:

На стороне клиента вам необходимо настроить поведение и установить это поведение в конечной точке клиента. Что-то вроде этого:

 <system.serviceModel>
    <behaviors>
        <endpointBehaviors>
            <behavior name="debug"> <dataContractSerializer maxItemsInObjectGraph="2147483647" />
            </behavior>
        </endpointBehaviors>
    </behaviors>
 

И вы устанавливаете поведение в конечной точке клиента:

 <endpoint name="myEndpoint" behaviorConfiguration="debug">
    Your other settings...
</endpoint>
 

Надеюсь, это поможет.

Комментарии:

1. Не могли бы вы опубликовать полную информацию об исключении? Возможно, мы чего-то не хватает.

2. Я обновил свой вопрос новой ошибкой, которую я получаю. Пожалуйста, посмотрите мою правку.

3. Вы уверены, что ваша привязка правильно сопоставлена как на сервере, так и на клиенте? Ссылается ли ваш тег службы на поведение <имя поведения=»Debug»>? как в <service behaviorConfiguration=»Debug»>?

4. ДА. Хотя у меня есть только <service> конфигурации на моем сервере и только <client> конфигурации на моем клиенте.

5. Я не уверен, поможет ли это вам. На стороне клиента вам необходимо настроить поведение и установить это поведение в конечной точке клиента. Что-то вроде этого: <system.ServiceModel> <behaviors> <endpointBehaviors> <имя поведения =»debug»> <DataContractSerializer MaxItemsInObjectGraph=»2147483647″ /> </behavior> </endpointBehaviors> </behaviors> И вы устанавливаете поведение в конечной точке клиента: <имя конечной точки =»myEndpoint» behaviorConfiguration = «debug»> Другие ваши настройки… </конечная точка>.

Ответ №2:

Лично я бы увеличил MaxReceivedMessageSize его, убедившись, что maxBufferSize он также отрегулирован. Это те общие области, которые нам необходимо было скорректировать.

Ответ №3:

Вот копия wsHttpBinding, которую я использовал в тестах для успешной передачи огромных объемов данных. Я не говорю, что эти значения являются лучшими практиками, но они работают для передачи больших объемов данных.

     <binding name="WSHttpBinding_LargeData" 
      maxBufferPoolSize="524288" 
      maxReceivedMessageSize="99999999">

      <readerQuotas 
         maxDepth="128" 
         maxStringContentLength="8192" 
         maxArrayLength="163840000" 
         maxBytesPerRead="4096" 
         maxNameTableCharCount="16384"
      />
    </binding>
 

Ответ №4:

Вы пробовали MaxItemsInObjectGraph в своем поведении службы

  <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
 

Комментарии:

1. У меня все то же NetDispatcherFaultException самое.

2. загрузите где-нибудь свой образец проекта и дайте мне знать, у меня так много подобных ошибок, когда я перенес свой финансовый бэк-офис из 10 старых удаленных приложений .net в WCF 🙂

3. Я нашел ответ благодаря Gabobcat . Спасибо за вашу помощь и ваше время! maxItemsInObjectGraph Свойство было тем, которое нужно было изменить.

4. когда вы сказали в своем отредактированном вопросе, что у вас одинаковые конфигурации как на клиенте, так и на сервере, я предположил, что у вас одинаковые настройки MaxItemsInObjectGraph на стороне сервера и клиента. В любом случае, хорошо, что вы разобрались, и я был полезен 🙂