Это именно то, для чего были созданы дуплексные привязки. Два лучших варианта: NetTcpBinding или PollingDuplexBinding .
Первый использует протокол TCP, который может не подходить для ваших клиентов, если их нет в вашей сети. Однако он допускает двустороннюю связь через инициируемый клиентом сокет. Таким образом, клиенту не нужно принимать входящие соединения. Я недавно использовал это в проекте, и он работает очень хорошо. Это также очень отзывчиво. Когда клиентские приложения закрываются, сеанс на сервере немедленно заканчивается.
Второй вариант, PollingDuplexBinding, включен в Silverlight SDK. Он использует инициированный клиентом «длинный» HTTP-запрос. Запрос ожидает сообщения, которые должны быть отправлены клиенту, и когда они приходят, клиентский запрос возвращается. Затем клиент инициирует новый HTTP-запрос обратно на сервер. Другими словами, у клиента всегда есть ожидающий HTTP-запрос. Это хорошо работает на брандмауэрах и должно использоваться, когда вы имеете дело с интернет-клиентами. Однако я обнаружил, что это не так быстро реагирует, как NetTcpBinding. Возможно, я что-то делал не так, но казалось, что попыткам отправить обратные вызовы на оставленные клиентские сеансы потребовалось время, чтобы «истекло время ожидания».
<Ч />
Вот пример файла конфигурации из моего недавнего проекта, который использовал NetTcpBinding для дуплексной связи. Обратите внимание, что помимо некоторых настроек для регулирования количества трафика я в значительной степени использую значения по умолчанию для этой привязки. Но есть всевозможные вещи , которые можно настроить, такие как receiveTimeout, inactivityTimeout и т. Д.
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="65535"
maxConcurrentSessions="65535"
maxConcurrentInstances="65535" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding maxConnections="65535">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="BroadcastService">
<endpoint address="" binding="netTcpBinding" contract="BroadcastService" />
</service>
</services>
</system.serviceModel>
</configuration>
<ч />
[ServiceContract( CallbackContract = typeof( IBroadcastCallback ) )]
[ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple )]
public class BroadcastService : IDisposable
{
[OperationContract(IsInitiating=true)]
public long Subscribe( Guid clientID )
{
// clients call this to initiate the session
}
[OperationContract(IsOneWay = true)]
public void Publish( BroadcastMessage message )
{
// client calls this to broadcast a message to
// all other subscribed clients via callback
}
}
[ServiceContract( Name = "BroadcastCallback" )]
public interface IBroadcastCallback
{
[OperationContract( IsOneWay = true, AsyncPattern = true )]
IAsyncResult BeginBroadcast(BroadcastMessage Message, AsyncCallback callback, object state);
void EndBroadcast( IAsyncResult asyncResult );
} // interface