После 8 месяцев работы над этой проблемой, 3 из них с Microsoft, вот решение. Краткий ответ: на стороне сервера (сторона, отправляющая большой файл) необходимо использовать для привязки следующее:
<customBinding>
<binding name="custom_tcp">
<binaryMessageEncoding />
<tcpTransport connectionBufferSize="256192" maxOutputDelay="00:00:30" transferMode="Streamed">
</tcpTransport>
</binding>
</customBinding>
Ключ здесь является атрибутом connectionBufferSize. Может потребоваться установка нескольких других атрибутов (maxReceivedMessageSize и т. Д.), Но виновником было connectionBufferSize.
Код на стороне сервера изменять не пришлось.
На стороне клиента не нужно было менять код.
Нет необходимости изменять конфигурацию на стороне клиента.
Вот длинный ответ:
Я все время подозревал, что причина net.tcp по WCF была медленной в том, что он отправлял небольшие порции информации очень часто, а не большие порции информации реже, и что это заставляло его работать плохо в сетях с высокой задержкой ( интернет). Это оказалось правдой, но это был долгий путь.
Есть несколько атрибутов на netTcpBinding, которые звучат многообещающе: maxBufferSize является наиболее очевидным, и maxBytesPerRead и другие, звучащие обнадеживающе, также. В дополнение к этому, можно создавать более сложные потоки, чем в исходном вопросе - вы также можете указать размер буфера там - как на стороне клиента, так и на стороне сервера. Проблема в том, что ничего из этого не имеет никакого влияния. Как только вы используете netTcpBinding, вы попадаете в шланг.
Причина этого заключается в том, что настройка maxBufferSize для netTcpBinding корректирует буфер на уровне протокола. Но вы ничего не можете сделать с netTcpBinding, чтобы когда-либо настроить базовый транспортный уровень. Вот почему нам так долго не удавалось добиться прогресса.
Настраиваемая привязка решает проблему, потому что увеличение connectionBufferSize на транспортном уровне увеличивает количество отправляемой информации за один раз, и, следовательно, передача гораздо менее подвержена задержке.
Решая эту проблему, я заметил, что maxBufferSize и maxBytesPerRead оказали влияние на производительность в сетях с низкой задержкой (и локально). Microsoft говорит мне, что maxBufferSize и connectionBufferSize являются независимыми и что все комбинации их значений (равные друг другу, maxBufferSize больше, чем connectionBufferSize, maxBufferSize меньше, чем connectionBufferSize), являются действительными. Мы добились успеха с maxBufferSize и maxBytesPerRead размером 65536 байт. Опять же, однако, это оказало очень небольшое влияние на производительность сети с высокой задержкой (исходная проблема).
Если вам интересно, для чего используется maxOutputDelay, это количество времени, которое отводится на заполнение буфера соединения до того, как платформа выдаст исключение ввода-вывода. Поскольку мы увеличили размер буфера, мы также увеличили время, отведенное на заполнение буфера.
Благодаря этому решению наша производительность увеличилась примерно на 400% и теперь немного лучше, чем IIS. Есть несколько других факторов, которые влияют на относительную и абсолютную производительность по сравнению с IIS по HTTP и WCF по net.tcp (и WCF по http, если на то пошло), но это был наш опыт.