WCF поточно предаване: Грешка в режим на рамкиране само в net.tcp

Имам един сървър за приложения, който прилага куп услуги, използвайки transferMode="Buffered" по подразбиране и една Streamed услуга. Той разкрива крайни точки за basicHttp и net.tcp протоколи и работи в производство при десетки IIS 7.0+ конфигурации без инциденти.

Когато отидох да репликирам архитектурата за сървър на ново приложение, стриймингът през net.tcp просто отказа да работи, изхвърляйки идеално непрозрачния и тъп ProtocolException

Използваният режим .Net Framing не се поддържа от MyNetTcpEndpointAddress. Вижте регистрационните файлове на сървъра за повече подробности.

Да, правилно, "сървърните регистрационни файлове". (Няма нищо, независимо дали е проследено или не.) Архитектурите на услугите и web.configs за S1 и S2 са идентични, с изключение на

  • някои промени в името
  • персонализирано пространство от имена в S2 (S1 използва темпури)
  • различни портове (и двата S1 и S2 използват портове в диапазона 8000-9000)

Услугата за поточно предаване S2 работи добре под basicHttp.

След като опитах всичко и не успях да накарам грешката да изчезне, създадох тестов клиент, който не прави нищо, освен да изпълнява моята архитектура на услуги с някои Ping методи. Без персонализирано пространство от имена, без излишни украшения, само оригиналните конфигурации и олекотени услуги, договори и ръчно кодирани обвивки около ChannelFactory прокситата.

Същата грешка:

Използваният режим .Net Framing не се поддържа от „net.tcp://localhost:9931/StreamingService.svc“. Вижте регистрационните файлове на сървъра за повече подробности.

Буферираната тестова услуга работи и при двата протокола, а услугата за поточно предаване работи под basicHttp, както в S2.

Всички тестове са извършени на една и съща машина с Win7 с пълна настройка на IIS. Тестовото приложение все още е твърде голямо, за да бъде публикувано тук, но ето пълните конфигурации и кода на конзолата

web.config

<configuration>
  <connectionStrings>
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <!-- throttling of stream size is partially controlled by this setting -->
    <httpRuntime maxRequestLength="1048576" /><!-- 1GB -->
  </system.web>
  <system.serviceModel>
    <serviceHostingEnvironment>
      <serviceActivations>
        <add relativeAddress="FooService.svc" service="WcfTest.Services.FooService" />
        <add relativeAddress="StreamingService.svc" service="WcfTest.Services.StreamingService" />
     </serviceActivations>
    </serviceHostingEnvironment>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <dataContractSerializer maxItemsInObjectGraph="200000" />
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding
                 openTimeout="00:20:00" sendTimeout="00:20:00" receiveTimeout="00:20:00" closeTimeout="00:20:00"
                 maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000">
          <readerQuotas maxStringContentLength="12000" />
        </binding>
        <binding name="WcfTest.Streaming.Http" transferMode="Streamed"
                 openTimeout="03:00:00" sendTimeout="03:00:00" receiveTimeout="03:00:00" closeTimeout="03:00:00"
                 maxReceivedMessageSize="1073741824" /><!-- 1GB -->
      </basicHttpBinding>
      <netTcpBinding>
        <binding
                 openTimeout="00:20:00" sendTimeout="00:20:00" receiveTimeout="00:20:00" closeTimeout="00:20:00"
                 maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000">
          <readerQuotas maxStringContentLength="12000" />
        </binding>
        <binding name="WcfTest.Streaming.Tcp" transferMode="Streamed"
                 openTimeout="03:00:00" sendTimeout="03:00:00" receiveTimeout="03:00:00" closeTimeout="03:00:00"
                 maxReceivedMessageSize="1073741824"><!-- 1GB -->
        </binding>
      </netTcpBinding>
    </bindings>
    <protocolMapping>
      <add scheme="http" binding="basicHttpBinding" />
      <add scheme="net.tcp" binding="netTcpBinding"/>
    </protocolMapping>
    <services>
      <service name="WcfTest.Services.Streaming">
        <!-- http -->
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="WcfTest.Streaming.Http" contract="WcfTest.Contracts.IStreamingService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <!-- net.tcp -->
        <endpoint address="" binding="netTcpBinding" bindingConfiguration="WcfTest.Streaming.Tcp" contract="WcfTest.Contracts.IStreamingService" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

app.config

<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior>
          <dataContractSerializer maxItemsInObjectGraph="200000"/>
        </behavior>
        <behavior name="customQuotaBehavior">
          <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding
                 openTimeout="00:20:00" sendTimeout="00:20:00" receiveTimeout="00:20:00" closeTimeout="00:20:00"
                 maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000">
          <readerQuotas maxStringContentLength="12000" />
        </binding>
        <binding name="WcfTest.Bindings.Streaming.Http" transferMode="Streamed"
                 openTimeout="03:00:00" sendTimeout="03:00:00" receiveTimeout="03:00:00" closeTimeout="03:00:00"
                 maxReceivedMessageSize="1073741824"><!-- 1GB -->
          </binding>
      </basicHttpBinding>

      <netTcpBinding>
        <binding
                 openTimeout="00:20:00" sendTimeout="00:20:00" receiveTimeout="00:20:00" closeTimeout="00:20:00"
                 maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000">
          <readerQuotas maxStringContentLength="12000" />
        </binding>
        <binding name="WcfTest.Bindings.Streaming.Tcp" transferMode="Streamed"
                 openTimeout="03:00:00" sendTimeout="03:00:00" receiveTimeout="03:00:00" closeTimeout="03:00:00"
                 maxReceivedMessageSize="1073741824"><!-- 1GB -->
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <!-- Foo -->
      <endpoint name="WcfTest.Endpoints.Foo.Http" address="http://localhost:9930/FooService.svc" binding="basicHttpBinding" contract="WcfTest.Contracts.IFooService" />
      <endpoint name="WcfTest.Endpoints.Foo.Tcp" address="net.tcp://localhost:9931/FooService.svc" binding="netTcpBinding" contract="WcfTest.Contracts.IFooService" />

      <!-- Streaming -->
      <endpoint name="WcfTest.Endpoints.Streaming.Http" address="http://localhost:9930/StreamingService.svc" binding="basicHttpBinding" bindingConfiguration="WcfTest.Bindings.Streaming.Http" contract="WcfTest.Contracts.IStreamingService" />
      <endpoint name="WcfTest.Endpoints.Streaming.Tcp" address="net.tcp://localhost:9931/StreamingService.svc" binding="netTcpBinding" bindingConfiguration="WcfTest.Bindings.Streaming.Tcp" contract="WcfTest.Contracts.IStreamingService" />
    </client>
  </system.serviceModel>
</configuration>

конзолно тестово повикване

static void Main(string[] args)
        {
            Console.WriteLine("starting WcfTest client...");

            Console.WriteLine();
            PingFoo(Contracts.Enums.Protocol.Http);
            PingFoo(Contracts.Enums.Protocol.Tcp);

            Console.WriteLine();
            PingStreaming(Contracts.Enums.Protocol.Http);
            // only this call errors:
            PingStreaming(Contracts.Enums.Protocol.Tcp);

            Console.WriteLine();
            Console.Write("ENTER to exit WcfTest client...");
            Console.ReadLine();
        }

        private static bool PingFoo(Contracts.Enums.Protocol protocol)
        {
            FooProxy pxy = new FooProxy(protocol);
            return PingProxy<IFooService>(pxy, protocol);
        }

        private static bool PingStreaming(Contracts.Enums.Protocol protocol)
        {
            StreamingProxy pxy = new StreamingProxy(protocol);
            return PingProxy<IStreamingService>(pxy, protocol);
        }

        private static bool PingProxy<T>(ProxyServiceBase<T> pxy, Contracts.Enums.Protocol protocol) where T : IServiceBase
        {
            bool success = pxy.Ping(); 
            Console.WriteLine("ping {0} {1}: {2}", pxy.GetType().Name, protocol, success ? " success" : " FAILED");
            if (pxy != null)
                pxy.Close();
            return success;
        }

Някакви идеи защо това би се провалило на един IIS сайт, по един от двата протокола, а не на друг? (Не е това.)

РЕДАКТИРАНЕ: В подготовка за приемането на тази страна на наградата, няколко пояснения относно тази тестова услуга и клиент:

Първо, по предложение на коментатор, svcutil работи добре срещу http, но не успява срещу net.tcp. Ето пълния резултат от това изпълнение:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin>svcutil net.tcp://localhost:9931/StreamingService.svc Microsoft (R) Service Model Metadata Tool [Microsoft (R) Windows (R) ) Communication Foundation, версия 3.0.4506.2152] Авторско право (c) Microsoft Corporation. Всички права запазени.

Опит за изтегляне на метаданни от „net.tcp://localhost:9931/StreamingService.svc“ с помощта на WS-Metadata Exchange. Този UR L не поддържа DISCO. Инструмент за метаданни на сервизния модел на Microsoft (R) [Microsoft (R) Windows (R) Communication Foundation, версия 3.0.4506.2152] Авторско право (c) Microsoft Corporation. Всички права запазени.

Грешка: Не могат да се получат метаданни от net.tcp://localhost:9931/StreamingService.svc

Ако това е услуга на Windows (R) Communication Foundation, до която имате достъп, моля, проверете дали сте активирали публикуването на метаданни на посочения адрес. За помощ при разрешаването на публикуването на метаданни, моля, вижте документацията на MSDN на адрес http://go.microsoft.com/fwlink/?LinkId=65455.

Грешка при обмен на WS-метаданни URI: net.tcp://localhost:9931/StreamingService.svc

Метаданните съдържат препратка, която не може да бъде разрешена: „net.tcp://localhost:9931/StreamingService.svc“.

Връзката с гнездото беше прекъсната. Това може да бъде причинено от грешка при обработката на вашето съобщение или изтичане на времето за получаване, превишено от отдалечения хост, или основен проблем с мрежовия ресурс. Времето за изчакване на локалния сокет беше „00:04:59.9929993“.

Съществуваща връзка беше принудително затворена от отдалечения хост

Ако искате повече помощ, напишете "svcutil /?"

Второ, премахването на "transferMode="Streamed" от Wcf.Bindings.Streaming.Tcp уеб и конфигурации на приложения, поставени по-горе, позволява на услугата да пингва добре. Това не подобрява ситуацията на svcutil.

И накрая, ето някои други неща, които опитах, без подобрение:

  • Различни версии на атрибута serviceMetadata в serviceBehaviors (което така или иначе разбирам, че е заменено от съществуването на крайни точки mex)
  • Различни с име serviceBehaviors вместо стандартното, което включвам
  • Различни конфигурации на security mode= на обвързването, особено None
  • Различни деактивации на всички други свързвания, крайни точки и т.н. с надеждата, че едно нещо може да пречи на друго

person downwitch    schedule 27.12.2013    source източник
comment
Поставете код от StreamingProxy за проверка.   -  person Jones    schedule 29.12.2013
comment
@Jones Няма нищо в това прокси. Отварянето на канала и Ping повикването се случват в ProxyServiceBase, което, както казах, е идентично с по-ранната услуга, която работи   -  person downwitch    schedule 30.12.2013
comment
Използване на svcutil net.tcp://localhost:9931/StreamingService.svc и проверка дали отговорът е правилен. Ако не е проблем при използване на журнал msdn.microsoft.com/ en-us/library/ms730064(v=vs.100).aspx за точка на откриване на грешката се появява точно   -  person Jones    schedule 30.12.2013
comment
@Jones Съжалявам, че отговарям толкова бавно... Получавам, че метаданните съдържат препратка, която не може да бъде разрешена като отговор от svcutil. Търсих много за това, но моите конфигурации на метаданни са добре (и, което е важно, същите, както бяха в предишната услуга/услуга за сравнение). Проследяването е активирано и в регистрационния файл няма грешка.   -  person downwitch    schedule 04.03.2014


Отговори (1)


Изглежда, че transferMode на tcp комуникацията или от страна на услугата, или от страната на клиента към Streamed, а другата страна все още използва режима по подразбиране, който е буфериран.

Забравяте ли нещо в "StreamingProxy" в случай на TCP?

Може би това ще помогне... http://social.msdn.microsoft.com/Forums/vstudio/en-US/37e32166-63f3-4cb9-ab81-14caa50cd91e/help-with-error-message-the-net-framing-mode-being-used-is-not-supported-by-?forum=wcf

Също така се опитвам да търся допълнително вашето решение...

person Dharmendra Mistry    schedule 10.03.2014
comment
Конфигурационните файлове на клиент (приложение) и сървър (уеб) са в оригиналната публикация, като и двата ясно посочват, че използват Streamed. Не знам какво Забравяте ли нещо в StreamingProxy в случай на TCP? означава, тъй като не настройвам протоколите си в код. - person downwitch; 11.03.2014
comment
Искам да кажа, че сте задали binding.TransferMode = TransferMode.Streamed в StreamingProxy клас на ping метод, дори ако сте го задали в app.config? (Както Джоунс каза и за кода). Опитвайки се да разбера дали wcf е конфигуриран правилно, тогава трябва да е клиент, който използва буфериран режим, тъй като и двете конфигурации изглеждат добре. - person Dharmendra Mistry; 15.03.2014