Сообщение увеличено при обмене сообщениями WCF - PullRequest
1 голос
/ 25 октября 2011

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

Мне иногда приходится обмениваться огромными данными, и я обнаружил 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 .: Это не проблема тайм-аута.


EDIT

Теперь у меня одинаковая конфигурация 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>

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

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

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

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

Ответы [ 4 ]

3 голосов
/ 25 октября 2011

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

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

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

EDIT:

На клиентской стороне вам нужно настроить поведение и установить это поведение в конечной точке клиента. Примерно так:

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

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

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

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

1 голос
/ 25 октября 2011

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

 <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
1 голос
/ 25 октября 2011

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

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

      <readerQuotas 
         maxDepth="128" 
         maxStringContentLength="8192" 
         maxArrayLength="163840000" 
         maxBytesPerRead="4096" 
         maxNameTableCharCount="16384"
      />
    </binding>
1 голос
/ 25 октября 2011

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

...