#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 на стороне сервера и клиента. В любом случае, хорошо, что вы разобрались, и я был полезен 🙂