Я боролся с этим в течение нескольких дней, буквально просматривая сто статей, дающих частичные рекомендации о том, как настроить службу WCF на основе TCP в веб-приложении. Если кто-то может мне помочь, я сделаю этот вопрос в полный.
Текущее состояние
Соединение net.tcp работает на моей машине разработки. Он также работает локально после развертывания на Windows Server 2008 R2. Тем не менее, он не работает удаленно, даже несмотря на то, что удаленно можно отправить telnet на порт 808 на сервере. Чтобы узнать подробности, прокрутите страницу до конца. Пожалуйста, помогите, если сможете.
Я создам новый вопрос для этой детали и обновляю этот вопрос с ответом, если я получу результат из него.
код
Я создал ServerHubService.svc
со следующим содержимым:
namespace Manage.SignalR
{
[ServiceContract]
public class ServerHubService
{
[OperationContract]
public void UpdateServerStatus(string serverStatus)
{
// Do something
}
}
}
Конфигурация приложения, на котором размещена служба
Следуя интерактивному учебнику, я добавил следующее к моему Web.config(я пробовал МНОГИЕ разные варианты). Это Web.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 и имеет привязку net.tcp
Я также перешел в "Дополнительные настройки" для веб-сайта и установил Enabled Protocols на http,net.tcp
Я удостоверился, что активирована функция активации HTTP без активации HTTP (и перезапущена). Это функция Windows, поэтому найдите "Включить или отключить функции Windows", чтобы найти это.
Подтверждение веб-приложения выполняется
Веб-сайт отлично работает для остальной части веб-приложения. Я установил test.mydomain.com, чтобы указать 127.0.0.1 в моем файле hosts
. Я даже могу посетить http://test.mydomain.com/SignalR/ServerHubService.svc, и он покажет мне хорошую автоматически созданную страницу из .NET, объяснив, как использовать эту службу.
Пока все хорошо.
Страница, сгенерированная .NET, позволяет мне использовать этот адрес для создания подключения к моей службе:
net.tcp://computername/SignalR/ServerHubService.svc/mex
Попытка подключения к службе как клиента
Если вы не запомните установку httpGetEnabled="true"
, вы получите сообщение об ошибке при попытке создать ссылку на службу. Если вы используете тестовый клиент WCF (также инструмент, включенный в Visual Studio) и не установили httpGetEnabled, вы получите сообщение об ошибке, как показано ниже:
Ошибка: невозможно получить метаданные из net.tcp://computername/SignalR/ServerHubService.svc/mex
Если это служба Windows (R) Communication Foundation, к которой вы получите доступ, убедитесь, что вы включили публикацию метаданных в указанный адрес. Чтобы помочь в публикации метаданных, пожалуйста, обратитесь к документации MSDN по адресу http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata
URI ошибки обмена: net.tcp://computername/SignalR/ServerHubService.svc/mex Метаданные содержит ссылку, которая не может быть решена: 'Net.tcp://computername/SignalR/ServerHubService.svc/mex. Не мог подключитесь к net.tcp://computername/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, он возвращает следующую ошибку:
Не удалось подключиться к net.tcp://computername/SignalR/ServerHubService.svc. Связь попытка длилась в течение 00: 00: 04.0002288. Код ошибки TCP 10061: соединение не может быть выполнено, поскольку активная целевая машина отказался.
Это внутренний стек, который включен с ошибкой:
Никакое соединение не может быть выполнено, поскольку активная целевая машина отказался [2001: 0: 5ef5: 79fb: 3884: a: a547: b2fd]: 808 at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) в System.Net.Sockets.Socket.Connect(EndPoint remoteEP) в System.ServiceModel.Channels.SocketConnectionInitiator.Connect(Uri uri, тайм-аут TimeSpan)
Если вы используете netstat -an |find /i "listening"
, чтобы увидеть, что ничто не слушает порт 808, вероятно, потому, что служба адаптера прослушивателя Net.Tcp не запущена.
Подтверждение
Теперь вызов проходит, но требуется подтверждение, прежде чем его можно будет объявить успешным. Мне нужно подтвердить, что на самом деле это net.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 в брандмауэре? Да.
- Брандмауэр отключен на сервере.
- Я могу подключиться к серверу на порту 808 извне с помощью
telnet mydomain.com 808
- В конфигурации службы на сервере было подтверждено следующее:
- baseAddress настроен на
net.tcp://mydomain.com:808/SignalR/ServerHubService.svc
- Это было
localhost
раньше, но сменилось наmydomain.com
после того, как оно не работало на сервере:<identity><dns value="mydomain.com" /></identity>
- baseAddress настроен на
- Он был протестирован с клиентом локально на сервере и на другом сервере. Оба могут подключаться к порту 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, и, возможно, определить, почему вызов не работает. Однако я понятия не имею, как анализировать это в настоящее время.
Удача
Я отказался и реализовал это в слое сокета. Он работал немедленно. Надеюсь, это может помочь кому-то еще. Я устанавливаю ответ, потому что многие из проблем были решены, и он действительно работал локально в конце концов, поэтому любая оставшаяся проблема, вероятно, связана со мной конкретной средой.