2011-06-02 71 views
0

请帮帮我!我试图建立一个应用程序使用回调contract.My应用程序工作正常客户端和服务器在同一台机器上,但是当我尝试从其他机器访问服务时,我得到了一个异常超时(操作din在分配的超时内没有完成)。客户端读取一些值将服务从服务器上的数据库中抛出。我不知道我的错误在哪里。我试图将客户端放在虚拟机中,服务(和数据库)在真机上。wcf wsdualhttpbinding超时问题

这里是我的服务器配置文件:

  <binding name="TrainService" closeTimeout="00:02:00" openTimeout="00:02:00" 
       receiveTimeout="00:10:00" sendTimeout="00:02:00" bypassProxyOnLocal="false" 
       transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
       messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
        maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" /> 
       <security mode="None"> 
        <message clientCredentialType="None" negotiateServiceCredential="true" 
         algorithmSuite="Default" /> 
       </security> 
      </binding> 
     </wsDualHttpBinding> 
     <wsHttpBinding> 
      <binding name="WSHttpBinding_ITrainService" closeTimeout="00:02:00" 
       openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:02:00" 
       bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
       messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" 
       allowCookies="false"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
        maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
        enabled="false" /> 
       <security mode="None"> 
        <transport clientCredentialType="None" proxyCredentialType="None" 
         realm="" /> 
        <message clientCredentialType="None" negotiateServiceCredential="true" 
         algorithmSuite="Default" /> 
       </security> 
      </binding> 
     </wsHttpBinding> 
    </bindings> 
    <client> 
    <endpoint address="http://localhost:8732/Design_Time_Addresses/WCFandEFService/TrainService/" 
     binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITrainService" 
     contract="TrainServiceRef.ITrainService" name="WSHttpBinding_ITrainService"> 
     <identity> 
     <dns value="localhost" /> 
     </identity> 
    </endpoint> 
    <endpoint address="net.tcp://localhost:8080/TcpService" binding="netTcpBinding" 
     contract="TrainServiceRef.ITrainService" name="NetTcpBinding_ITrainService" /> 
    <endpoint address="http://localhost:8082/InterlockingService/Host/line" 
     binding="wsDualHttpBinding" bindingConfiguration="LineService" 
     contract="InterlockingServiceReference.ILineService" name="LineService"> 
     <identity> 
     <userPrincipalName value="Romina-PC\Romina" /> 
     </identity> 
    </endpoint> 

    <endpoint address="http://localhost:8082/InterlockingService/Host/trains" 
     binding="wsDualHttpBinding" bindingConfiguration="TrainService" 
     contract="InterlockingServiceReference.ITrainService" name="TrainService"> 
     <identity> 
     <userPrincipalName value="Romina-PC\Romina" /> 
     </identity> 
    </endpoint> 

    </client> 

</system.serviceModel> 

我的客户端配置文件:

- >

  <binding name="TrainService" closeTimeout="00:01:00" openTimeout="00:01:00" 
       receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" 
       transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferPoolSize="52428800" maxReceivedMessageSize="6553600" 
       messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1638400" 
        maxBytesPerRead="4096" maxNameTableCharCount="1638400" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" /> 
       <security mode="None"> 
        <!--<message clientCredentialType="None" negotiateServiceCredential="true" 
         algorithmSuite="Default" />--> 
       </security> 
      </binding> 
     </wsDualHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="http://localhost:8082/InterlockingService/Host/line" 
      binding="wsDualHttpBinding" bindingConfiguration="LineService" 
      contract="InterlockingServiceRef.ILineService" name="LineService"> 
      <identity> 
       <userPrincipalName value="Romina-PC\Romina" /> 
      </identity> 
     </endpoint> 

     <endpoint address="http://localhost:8082/InterlockingService/Host/trains" 
      binding="wsDualHttpBinding" bindingConfiguration="TrainService" 
      contract="InterlockingServiceRef.ITrainService" name="TrainService"> 
      <identity> 
       <userPrincipalName value="Romina-PC\Romina" /> 
      </identity> 
     </endpoint> 
    </client> 
</system.serviceModel> 

谢谢。

那些是合同:公共接口ITrainServiceCallBack { [OperationContract的(IsOneWay =真)] 空隙OnTrainChangeState(TrainData列车); }

//[ServiceContract(Name = "LineService", CallbackContract = typeof(ILineServiceCallBack))] 
[ServiceContract(CallbackContract = typeof(ITrainServiceCallBack))] 
public interface ITrainService 
{ 
    [OperationContract] 
    TrainData GetTrainData(string trainName); 

    [OperationContract] 
    bool ChangeTrainState_bool(ref TrainData train); 

    [OperationContract] 
    void ChangeTrainState(ref Trains_Detail train); 
    [OperationContract] 
    bool SubscribeToTrainChangeEvent(); 

    [OperationContract] 
    bool UnSubscribeFromTrainChangeEvent(); 
    [OperationContract] 
    TrainData TranslateTrainEntityToTrainData(Trains_Detail trainEntity); 

    [OperationContract] 
    IEnumerable<Trains_Detail> GetTrains(); 

    [OperationContract] 
    IEnumerable<Trains_Detail> GetTrains_ByStation(int Statie_plecare, int Statie_sosire); 
} 

方法实现:使用系统

; using System.Collections.Generic;使用System.Linq的 ; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.Data;

命名空间WCFandEFService //注意:您可以在“重构”菜单上使用“重命名”命令将代码和配置文件中的类名“ProductService”一起更改。 // [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]

public partial class InterlockingService : ITrainService 
{ 

    static List<ITrainServiceCallBack> subscribers_train = new List<ITrainServiceCallBack>(); 


    public bool TrainExists(string nrTren, InterlockingEntities database) 
    { 
     // Check to see whether the specified product exists in the database 
     int numTrain = (from t in database.Trains_Details 
         where string.Equals(t.Nr_tren, nrTren) 
         select t).Count(); 

     return numTrain > 0; 

    } 


    public TrainData TranslateTrainEntityToTrainData(Trains_Detail trainEntity) 
    { 
     TrainData train = new TrainData(); 

     train.nrTren=trainEntity.Nr_tren; 
     train.ora_Plecare= trainEntity.Ora_plecare; 
     train.ora_Sosire=trainEntity.Ora_sosire; 
     train.statie_Plecare=trainEntity.Statie_plecare; 
     train.statie_Sosire=trainEntity.Statie_sosire; 
     train.rang=trainEntity.Rang; 
     train.observatii=trainEntity.Observatii;    
     train.RowVersion=trainEntity.RowVersion; 

     return train; 

    } 

    #region ILineService Members 



    public IEnumerable<Trains_Detail> GetTrains() 
    { 
     InterlockingEntities context = new InterlockingEntities(); 


     IEnumerable<Trains_Detail> result = 
       (from t in context.Trains_Details 
       //where l.Station == station 
       select t); 
     return result; 

    } 

    public IEnumerable<Trains_Detail> GetTrains_ByStation(int Statie_plecare,int Statie_sosire) 
    { 
     InterlockingEntities context = new InterlockingEntities(); 

     IEnumerable<Trains_Detail> result = 
       (from t in context.Trains_Details 
       where t.Statie_plecare==Statie_plecare && t.Statie_sosire==Statie_sosire 
       select t); 
     return result; 

    } 



    public TrainData GetTrainData(string trainNr) 
    { 
     InterlockingEntities context = new InterlockingEntities(); 
     Trains_Detail trainInDB = 
      (from t 
       in context.Trains_Details 
       where String.Compare(t.Nr_tren, trainNr) == 0 
       select t).FirstOrDefault(); 
     if (trainInDB == null) 
     { 

      throw new Exception("No line cu numele " + trainInDB.Nr_tren); 

     } 

     context.Detach(trainInDB); 
     return TranslateTrainEntityToTrainData(trainInDB); 
    } 

    public bool ChangeTrainState_bool(ref TrainData train) 
    { 
     InterlockingEntities context = new InterlockingEntities(); 
     String trainName = train.nrTren; 
     //int lineStation = line.station; 
     Trains_Detail trainInDB = 
      (from t 
       in context.Trains_Details 
       where String.Compare(t.Nr_tren, trainName) == 0 
       select t).FirstOrDefault(); 

     if (trainInDB == null) 
     { 
      throw new Exception("No train cu numele " + trainInDB.Nr_tren); 
     } 

     context.Detach(trainInDB); 


     trainInDB.Nr_tren = train.nrTren; 
     trainInDB.Ora_plecare=train.ora_Plecare; 
     trainInDB.Ora_sosire=train.ora_Sosire; 
     trainInDB.Statie_plecare=train.statie_Plecare; 
     trainInDB.Statie_sosire=train.statie_Sosire; 
     trainInDB.Rang=train.rang; 

     trainInDB.RowVersion = train.RowVersion; 

     context.Attach(trainInDB); 

     context.ObjectStateManager.ChangeObjectState(trainInDB, System.Data.EntityState.Modified); 
     context.SaveChanges(); 
     train.RowVersion = trainInDB.RowVersion; 
     context.Dispose(); 
     raiseTrainChangeState(TranslateTrainEntityToTrainData(trainInDB)); 
     return true; 
    } 


    public void ChangeTrainState(ref Trains_Detail train) 
    { 
     using (var context = new InterlockingEntities()) 
     { 
      context.Attach(train); 
      context.ObjectStateManager.ChangeObjectState(train, EntityState.Modified); 
      context.SaveChanges(); 
     } 
    } 
    } 


    public bool SubscribeToTrainChangeEvent() 
    { 
     try 
     { 
      ITrainServiceCallBack callback = OperationContext.Current.GetCallbackChannel<ITrainServiceCallBack>(); 

      if (!subscribers_train.Contains(callback)) 
      { 
       subscribers_train.Add(callback); 
      } 
      return true; 
     } 
     catch (Exception) 
     { 

      return false; 
     } 


    } 

    public bool UnSubscribeFromTrainChangeEvent() 
    { 
     try 
     { 
      ITrainServiceCallBack callback = OperationContext.Current.GetCallbackChannel<ITrainServiceCallBack>(); 
      subscribers_train.Remove(callback); 

      return true; 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 

    #endregion 




    private void raiseTrainChangeState(TrainData train) 
    { 
     subscribers_train.AsParallel().ForAll(callback => 
     { 
      if (((ICommunicationObject)callback).State == CommunicationState.Opened) 
      { 
       callback.OnTrainChangeState(train); 

      } 
      else 
      { 
       subscribers_train.Remove(callback); 
      } 
     }); 
    } 






} 

}

+0

你想分享的合同结构和操作的实施? – SaravananArumugam 2011-06-02 18:04:00

+0

请参阅我答案中的编辑部分。检查是否有帮助。 – SaravananArumugam 2011-06-02 18:21:56

回答

-1

检查一下您是否标明您的操作合同的一种方式。它通常会在双http绑定中超时,因为人们无法将合同标记为一种方式。

[OperationContract(IsOneWay = true)] 

编辑

请将服务合同中的行为,下面一行。

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 

对于我们的参考,请考虑发布您的服务合同结构和运营合同的实施。

+0

所有我的操作契约?因为我把所有isoneway = true,我得到以下错误:System.InvalidOperationException:标记为IsOneWay = true的操作不得声明输出参数,通过引用参数或返回值。 – 2011-06-02 15:38:54

+0

wsDualHttpBinding是双工通信绑定。实质上,它将在一个通道中调用并在另一个通道中接收。所以当你打电话时,你应该预期你只是做一个只打电话(回复将在不同的频道收到),并且不会期望任何输出作为你的呼叫的回应。 – SaravananArumugam 2011-06-02 17:14:43

+0

WSDualHttpBinding确实支持非单向(即请求/回复)操作,您不需要将操作设置为单向操作。 – carlosfigueira 2011-06-02 17:16:46

0

您的端点地址在客户端和服务器中指定“localhost”作为机器名称。如果他们在不同的机器上,客户将无法与服务交谈。尝试将其更改为服务器所在的实际机器名称。

更新:这里是WSDualHttpBinding在合同和回调合同中使用非单向操作的示例。 WSDualHttpBinding 不要求要求在回调合约上的操作成为一种方式。 PollingDuplexHttpBinding(用于Silverlight)确实如此,但这是另一回事。

using System; 
using System.IO; 
using System.Reflection; 
using System.ServiceModel; 
using System.Threading; 

public class StackOverflow_6216605_751090 
{ 
    [ServiceContract(CallbackContract = typeof(ITestCallback))] 
    public interface ITest 
    { 
     [OperationContract] 
     int Add(int x, int y); 
     [OperationContract] 
     void CallMe(int numberOfTimes); 
    } 
    [ServiceContract] 
    public interface ITestCallback 
    { 
     [OperationContract] 
     string Hello(string name); 
    } 
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 
    public class Service : ITest 
    { 
     public int Add(int x, int y) 
     { 
      Console.WriteLine("In a Request/Reply operation on server: {0} + {1}", x, y); 
      return x + y; 
     } 

     public void CallMe(int numberOfTimes) 
     { 
      Console.WriteLine("In another request/reply operation on server, which will call the client."); 
      ITestCallback callback = OperationContext.Current.GetCallbackChannel<ITestCallback>(); 
      ThreadPool.QueueUserWorkItem(delegate 
      { 
       for (int i = 0; i < numberOfTimes; i++) 
       { 
        Console.WriteLine("Received from client: {0}", callback.Hello("Server")); 
       } 
      }); 
     } 
    } 
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 
    public class ClientCallback : ITestCallback 
    { 
     static int count = 0; 
     public string Hello(string name) 
     { 
      Console.WriteLine("In a client operation, name = {0}", name); 
      return string.Format("[{0}] Hello, {1}", ++count, name); 
     } 
    } 
    static void PrintUsage() 
    { 
     string programName = Path.GetFileName(Assembly.GetEntryAssembly().CodeBase); 
     Console.WriteLine("Usage: {0} <options>", programName); 
     Console.WriteLine("Examples:"); 
     Console.WriteLine(" Starting the server: {0} -server", programName); 
     Console.WriteLine(" Starting the client: {0} -client <serverMachineName>", programName); 
    } 
    public static void Main(string[] args) 
    { 
     if (args.Length < 1) 
     { 
      PrintUsage(); 
      return; 
     } 

     if (args[0].Equals("-server", StringComparison.OrdinalIgnoreCase)) 
     { 
      string serviceAddress = "http://" + Environment.MachineName + ":8000/Service"; 
      ServiceHost host = new ServiceHost(typeof(Service), new Uri(serviceAddress)); 
      host.AddServiceEndpoint(typeof(ITest), new WSDualHttpBinding(WSDualHttpSecurityMode.None), ""); 
      host.Open(); 
      Console.WriteLine("Host opened, press ENTER to close"); 
      Console.ReadLine(); 
      host.Close(); 
     } 
     else if (args.Length > 1 && args[0].Equals("-client", StringComparison.OrdinalIgnoreCase)) 
     { 
      string serviceAddress = "http://" + args[1] + ":8000/Service"; 
      ClientCallback clientCallback = new ClientCallback(); 
      DuplexChannelFactory<ITest> factory = new DuplexChannelFactory<ITest>(
       clientCallback, 
       new WSDualHttpBinding(WSDualHttpSecurityMode.None), 
       new EndpointAddress(serviceAddress)); 
      ITest proxy = factory.CreateChannel(); 
      Console.WriteLine("Simple Request/Reply: {0}", proxy.Add(3, 4)); 
      Console.WriteLine("Now calling an operation on the server which will cause callbacks"); 
      proxy.CallMe(10); 
      Console.WriteLine("Press ENTER to close"); 
      Console.ReadLine(); 
     } 
     else 
     { 
      PrintUsage(); 
     } 
    } 
} 
+0

嗨@carlosfigueira,你介意在WSHttpBinding支持请求/响应类型的通信的地方以及如何显示一个例子吗? – SaravananArumugam 2011-06-02 17:24:34

+0

我不确定请求/响应类型消息交换将如何计算为双工。请参阅http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/15841cf6-b6bb-492a-915c-340b1cbb890d/进行类似的对话。 – SaravananArumugam 2011-06-02 17:38:11

+0

通过双工,这意味着服务可以随时向客户端发送请求 - 即客户端不需要执行某些操作,例如轮询服务器以查找消息。 WSDualHttpBinding实际上在客户端创建了一个服务器,并且在初始握手过程中,客户端向服务器发送将要侦听消息的地址。 – carlosfigueira 2011-06-02 17:55:11

1

合同的回调的经营合同(或多个)应注明IsOneWay = true,并且应该返回void - 在服务中不是所有的业务合同。

此外,我有一个类似的问题,使用NetTcpBinding双工合同。我通过在代理上设置OperationTimeout值解决了这个问题(在我的情况下为5分钟)。我通过在创建频道时将我的频道投射到客户端上的IContextChannel接口来以编程方式进行设置。您应该可以在客户端配置文件中执行相同的操作。

我的代码:

((IContextChannel)myChannel).OperationTimeout = new Timespan(0, 5, 0); 
+0

我已修改所有您的建议,但它不起作用。同样的错误信息(10分钟 - >操作din不完成在分配的超时)。其他建议?感谢您的回复 – 2011-06-02 18:00:04

+0

操作WSDualHttpBinding回调合同*不*需要标记为一种方式。 – carlosfigueira 2011-06-02 18:12:52