Настройка службы WCF TCP в веб-приложении

я боролся с этим в течение нескольких дней, буквально проходя через сто статей, дающих частичные рекомендации о том, как настроить службу на основе WCF TCP в веб-приложении. Если кто-то может мне помочь, я сделаю этот вопрос полное руководство.

текущее состояние

сеть.TCP-соединение работает на моей машине разработки. Он также работает локально после развертывания в Windows Server 2008 R2. Однако, это не работайте удаленно, даже если возможно telnet к порту 808 на сервере удаленно. Прокрутите вопрос до конца, чтобы узнать подробности. Пожалуйста, помогите, если сможете.

я создам новый вопрос для этой детали и обновлю этот вопрос с ответом, если я получу результат.

код

я создал ServerHubService.svc следующего содержания:

namespace Manage.SignalR
{
    [ServiceContract]
    public class ServerHubService
    {
        [OperationContract]
        public void UpdateServerStatus(string serverStatus)
        {
            // Do something
        }
    }
}

Настройки Приложения-хостинг сервис

после онлайн-учебника я добавил следующее в свой веб-сайт.config (я пробовал много разных вариантов). Это паутина.конфигурация веб-приложения, в котором размещается служба, к которой я позже хочу подключиться с помощью TCP.

<configuration>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="ServerHubBehavior"
      name="Manage.SignalR.ServerHubService">
        <endpoint address=""
              binding="netTcpBinding"
              bindingConfiguration="portSharingBinding"
              name="MyServiceEndpoint"
              contract="Manage.SignalR.ServerHubService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>

        <endpoint address="mex"
              binding="mexTcpBinding"
              bindingConfiguration=""
              name="MyServiceMexTcpBidingEndpoint"
              contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://test.mydomain.com:808/SignalR/ServerHubService.svc" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServerHubBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="portSharingBinding" portSharingEnabled="true"/>
      </netTcpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      minFreeMemoryPercentageToActivateService="0" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
</configuration>

httpGetEnabled="true" важно, потому что в противном случае вы не можете создать ссылку на службу.

конфигурация сервера, на котором выполняется веб-приложение

я настройка этого на моей машине разработки, которая имеет IIS 7.5

я прочитал, что IIS Express (встроенный в Visual Studio) не поддерживает net.tcp, поэтому я создал новый веб-сайт в IIS 7.5 с помощью .NET 4.5 и имеет сеть.привязка tcp

bindings in IIS

я также пошел в Расширенные настройки для веб-сайта и установил включенные протоколы в http,net.tcp

я гарантировал, что активация Windows, не связанная с HTTP, включена (и перезапущена). Это функция Windows поэтому найдите "Включить или выключить функции Windows", чтобы найти это.

enter image description here

подтверждение запуска веб-приложения

сайт работает для остальной части веб-приложения. Я установил test.mydomain.com чтобы указать на 127.0.0.1 в my . Я даже могу посетить http://test.mydomain.com/SignalR/ServerHubService.svc и он покажет мне хорошую автоматически сгенерированную страницу из .NET, объясняя, как использовать это услуга.

пока все хорошо.

страница, сгенерированная .NET, говорит мне использовать этот адрес для создания подключения к моей службе:

net.tcp://computername/SignalR/ServerHubService.svc/mex

попытка подключения к сервису в качестве клиента

если вы не помните, чтобы установить httpGetEnabled="true" вы получите сообщение об ошибке при попытке создать ссылку на службу к нему. Если вы используете тестовый клиент WCF (также инструмент, включенный в Visual Studio) и не установили httpGetEnabled, вы получите ошибка, подобная следующей:

ошибка: не удается получить метаданные из сеть.tcp://имя_компьютера / SignalR / ServerHubService.svc / mex

если это служба Windows (R) Communication Foundation, к которой вы имейте доступ, пожалуйста, проверьте, что вы включили публикацию метаданных по адресу указанный адрес. Для получения справки о публикации метаданных, пожалуйста см. документацию MSDN на http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata

URI ошибки Exchange: сеть.tcp://имя_компьютера / SignalR / ServerHubService.метаданные svc/mex содержит ссылку, которая не может быть разрешена: инет.tcp://имя_компьютера / SignalR / ServerHubService.svc / mex'. Не могла подключение к сети.tcp://имя_компьютера / SignalR / ServerHubService.svc / mex. Попытка подключения продолжалась в течение периода времени 00:00: 04.0032289.

код ошибки TCP 10061: нет соединение может быть сделано, потому что цель машина активно отказывалась от него [2001:0:4137:9e76:c81:a4c:a547:b2fd]: 808. Не удалось установить соединение, так как целевая машина активна отказано [2001: 0:4137:9e76:c81:a4c:a547:b2fd]: 808

однако, если вы сделали все, как указано выше, вы должны иметь возможность добавить ссылку на службу.

вызов методов в службе

при попытке вызвать простой метод Hello World в Службе из тестового клиента WCF возвращается следующая ошибка:

не удалось подключиться к сеть.tcp://имя_компьютера / SignalR / ServerHubService.ВПВ. Соединение попытка продолжалась в течение промежутка времени 00:00: 04.0002288. Код ошибки TCP 10061: подключение не может быть сделано, потому что целевая машина активно отказаться от него.

это внутренний stacktrace, который включен в с ошибкой:

не удалось установить соединение сделал, потому что целевая машина активно отказался от него [2001:0:5ef5: 79fb: 3884:a:a547: b2fd]: 808 at Система.Сеть.Розетки.Розетка.DoConnect (EndPoint endPointSnapshot, SocketAddress socketAddress) на Система.Сеть.Розетки.Розетка.Подключение (конечная точка remoteEP) на Система.Средство servicemodel.Каналы.SocketConnectionInitiator.Подключение (Uri uri, TimeSpan timeout)

если вы используете netstat -an |find /i "listening" чтобы увидеть, что ничто не прослушивает порт 808, это, вероятно, потому, что сеть.Прослушиватель Tcp Служба адаптера не запущена.

подтверждение

звонок проходит, но какое-нибудь подтверждение, прежде чем он может быть объявлен успешным. Мне нужно подтвердить, что это на самом деле чистая.вызов tcp на порту 808 и фактически не вызов на конечной точке http. Я пытаюсь сделать это с Wireshark, но он не появляется, вероятно, потому, что это вызов, происходящий от и до моего местного машина.

развертывание

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

он не работает после публикации в Windows Server 2008 R2. Это дает общее SocketException: An existing connection was forcibly closed by the remote host.

он хорошо работает локально на сервере, но он не работает удаленно.

вот контрольный список, используемый для проверки сервер:

  • - это Net.Tcp Listener Adapter сервис работает? Да
  • привязка сайта IIS к net.tcp значение 808:*? Да
  • включены протоколы в расширенных настройках для сайта в IIS, установленных в http,net.tcp? Да
  • сервер прослушивает порт 808? Да, проверено с netstat -an |find /i "listening"
  • открыт ли порт 808 в брандмауэре? Да.
    • Брандмауэр отключен на сервере.
    • я могу telnet серверу на порт 808 извне с telnet mydomain.com 808
  • в конфигурации службы на сервере было подтверждено следующее:
    • baseAddress настроен на net.tcp://mydomain.com:808/SignalR/ServerHubService.svc
    • это localhost раньше, но изменен на mydomain.com после того, как он не работает на сервере: <identity><dns value="mydomain.com" /></identity>
  • он был протестирован с клиентом локально на сервере и на другом сервере. Оба могут подключение к порту 808 с telnet и оба дают то же сообщение об ошибке.

какая конфигурация может отсутствовать на сервере? Я так близок к цели. Пожалуйста, помогите мне в устранении неполадок и заполните вопрос.

вот конфигурация клиента на сервере, вызывающем службу:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="MyServiceEndpoint" />
    </netTcpBinding>
  </bindings>
  <client>
    <endpoint address="net.tcp://mydomain.com:808/SignalR/ServerHubService.svc"
      binding="netTcpBinding" bindingConfiguration="MyServiceEndpoint"
      contract="ServerHubService.ServerHubService" name="MyServiceEndpoint">
      <identity>
        <dns value="mydomain.com" />
      </identity>
    </endpoint>
  </client>
</system.serviceModel>

я также попытался без 808, настроенного в конечной точке, поскольку это, по слухам, порт по умолчанию для net.соединение TCP. Однако результат все тот же.

вместо того, чтобы пытаться много вещей случайным образом, хороший вопрос, возможно: как отлаживать что-то вроде этого? могу ли я установить программу на любом сервере, которая скажет мне, почему этот вызов блокируется?

С Wireshark настроен таким образом, можно посмотреть на вызов, поступающий на сервер на порту 808 и, возможно, определить, почему вызов не работает. Однако, я понятия не имею как анализировать это настоящее время.

wireshark

удачи

я сдался и вместо этого реализовал это в слое сокета. Это сработало немедленно. Надеюсь, это поможет кому-то еще. Я устанавливаю ответ, потому что многие проблемы были решены, и в конечном итоге он работал локально, поэтому любая оставшаяся проблема, вероятно, связана с конкретной средой.

7 ответов


вы должны создать прокси-сервер на основе метаданных, предоставляемых через HTTP для tcp.(убедитесь, что httpGetEnabled имеет значение true). Адрес, который вы используете на клиенте, должен быть размещенным адресом. Пожалуйста, обратитесь к приведенному ниже сообщению.

http://blogs.msdn.com/b/swiss_dpe_team/archive/2008/02/08/iis-7-support-for-non-http-protocols.aspx


в вашем вопросе вы упомянули, что вы подключились к "test.mydomain.com" но ошибка изменила сервер на "computername". Затем в своем комментарии Вы упомянули, что он все еще не подключается. Если вы хотите, чтобы псевдоним возвращался в WSDL / MEX, добавьте узел useRequestHeadersForMetadataAddress в поведение службы. Вот информация MSDN на этом узле:MSDN useRequestHeadersForMetadataAddress узел

вот как должна выглядеть ваша конфигурация. Этот учитывает ответ, данный Prasath (httpGetEnabled="true").

<serviceBehaviors>
   <behavior name="ServerHubBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
      <useRequestHeadersForMetadataAddress>
         <defaultPorts>
            <add scheme="net.tcp" port="808" />
         </defaultPorts>
      </useRequestHeadersForMetadataAddress>
   </behavior>
</serviceBehaviors>

хостинг службы на основе TCP в IIS всегда был медведем. WCF позволяет очень легко запускать собственный хост службы, прослушивая ваш TCP-порт. Моя рекомендация состояла бы в том, чтобы сделать это и настроить его для запуска в качестве службы Windows.

см. эту статью:http://msdn.microsoft.com/en-us/library/ff649818.aspx


Я предполагаю, что проблема заключается в том, что вам нужно настроить SPN (имя участника-службы) для вашей службы WCF (на машине) и добавить его в учетную запись службы, под которой работает служба.

Если вы используете его под пользователем пула приложений по умолчанию, вам нужно настроить SPN для машины.

Я знаю, что это беспокоит, и, как правило, сюрприз ждет от нас разработчиков, как только наша служба будет готова к развертыванию в производство или предпроизводственные среды.

SPN используется Kerberos в процессе проверки подлинности.

попробуйте использовать IP-адрес компьютера для разрешения службы вместо имени хоста. (Это не должно требовать SPN), заменить". test.mydomain.com " по IP-адресу машины:

<host>
    <baseAddresses>
        <add baseAddress="net.tcp://192.168.0.253:808/SignalR/ServerHubService.svc" />
    </baseAddresses>
</host>

взгляните на эти статьи: - Kerberos для занятого администратора
- WCF в интрасети с проверкой подлинности windows
- Для следующий пост, попробуйте прочитать тот, который не принимается в качестве ответа:какой SPN мне нужно установить для сети.служба tcp?


вы пытались разместить службу (для целей тестирования) в службе Windows на вашем локальном компьютере? Таким образом, вы, по крайней мере, будете знать, является ли проблема на стороне службы или это конфигурация IIS/server.


вы Net.Служба совместного использования портов TCP работает на сервере я думаю... я не нашел его ясно изложенным.


сегодня у меня была аналогичная проблема, при вызове нет.служба tcp wcf изнутри asp.net Web api. Я не скажу, что со всех других машин эта служба работала годами, но вызовы были сделаны WCF self hosting, WCF iis asp.net совместимость хостинга - > против сети.служба tcp самостоятельно размещена. Когда я опубликовал свой простой веб-api, вызывающий ту же сеть.служба tcp, все пошло не так, и все соединение было прервано без каких-либо причин, даже полная трассировка wcf обе стороны (сервис и клиент) не помогли, просто сказав одно и то же "Соединение прервано".

Я уже знал, что нет.tcp поставляется с включенной защитой над транспортом, используя аутентификацию windows для подписи и шифрования связи, поэтому я просто попытался отключить безопасность, и все начинает работать правильно.

просто попробуйте отключить безопасность таким образом с обеих сторон (клиент и служба):

<security mode="None"/>

полный сервис привязка:

<netTcpBinding>

    <binding name="netTcpBinding" portSharingEnabled="true">

        <security mode="None"/>

    </binding>

</netTcpBinding>

Я надеюсь, это может помочь вам тоже.