在客户端和WCF服务之间与netTcpBinding建立单一连接

时间:2012-01-17 09:33:00

标签: wcf-binding

我在MSDN上遇到了一个页面,解释了WCF服务here中的事务。我调整了绑定设置并使用了netTcpBinding。这是我的app.config文件的serviceModel部分:

  <system.serviceModel>
<bindings>
  <netTcpBinding>
    <binding name="netTcpBindingConfiguration1" transactionFlow="true">
      <security mode="Message" />
    </binding>
  </netTcpBinding>
</bindings>
<services>
  <service name="OrderingService.OrderService">
    <clear />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"
      listenUriMode="Explicit">
    </endpoint>
    <endpoint address="net.tcp://localhost:8880/OrderingService"
      binding="netTcpBinding" bindingConfiguration="netTcpBindingConfiguration1"
      contract="OrderingService.IOrderService" />
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8888/OrderingService/" />
      </baseAddresses>
    </host>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceMetadata httpGetEnabled="True" />
      <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
  </serviceBehaviors>
</behaviors>

我创建了一个Windows应用程序作为服务的客户端。我使用netstat命令查看客户端和服务之间的TCP连接(托管在控制台应用程序中)。我意识到每个操作(在我的客户端应用程序中点击按钮,通过调用服务的代理类的方法来放置新订单),会创建一个新连接,并且所有以前的连接仍然保持ESTABLISHED。显然,这不是一个理想的条件。我想知道我做错了什么以及通过减少只有一个的连接数来解决这个问题的设置或配置。顺便说一下,实现服务接口的服务类将InstanceContextMode设置为PerSession。这是合同接口和服务类:

[ServiceContract(SessionMode=SessionMode.Required)]
public interface IOrderService
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.NotAllowed)]
    List<Customer> GetCustomers();

    [OperationContract]
    [TransactionFlow(TransactionFlowOption.NotAllowed)]
    List<Product> GetProducts();

    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    string PlaceOrder(Order order);

    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    string AdjustInventory(int productId, int quantity);

    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    string AdjustBalance(int customerId, decimal amount);
}

[ServiceBehavior(TransactionIsolationLevel = IsolationLevel.Serializable,
    TransactionTimeout = "00:00:20",
    InstanceContextMode = InstanceContextMode.PerSession,
    TransactionAutoCompleteOnSessionClose = true)]
public class OrderService : IOrderService
{...}

以下是在客户端应用中使用代理类的代码:

using (TransactionScope scope = new TransactionScope())
        {
            try
            {
                proxy = new OrderServiceClient("NetTcpBinding_IOrderService");
                result = proxy.PlaceOrder(order);
                MessageBox.Show(result);

                result = proxy.AdjustInventory(product.ProductId, quantity);
                MessageBox.Show(result);

                result = proxy.AdjustBalance(customer.CustomerId, product.Price * quantity);
                MessageBox.Show(result);
                proxy.Close();
                scope.Complete();
            }
            catch (Exception exc)
            {
                MessageBox.Show("Error occurred: " + exc.Message);
            }
        }

1 个答案:

答案 0 :(得分:0)

关于TCP连接保持ESTABLISHED - 你在完成它时在你的客户端实例上调用.Close()吗?

如果要使用单个连接,则应将实例上下文模式更改为“单个”,并重复使用在客户端中建立的连接来处理所有服务调用。这适合您希望在服务中保持状态的架构。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class Service : IService
{
}

当我在WCF中了解上下文模式时,我发现此链接非常有用:CodeProject link

由于您当前正在使用PerSession上下文模式,因此您应该可以通过在行为部分中添加maxConcurrentSessions设置将其限制为单个连接。你可以这样做:

  <serviceBehaviors>
    <behavior>
      <serviceMetadata httpGetEnabled="True" />
      <serviceDebug includeExceptionDetailInFaults="False" />
      <serviceThrottling maxConcurrentSessions="1" />
    </behavior>
  </serviceBehaviors>

如果你有一个客户,这只是一个好主意。