2011-06-02 103 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