简体   繁体   中英

wcf wsdualhttpbinding timeout problem

Please help me!!!

I am trying to build an application which uses callbacks contracts.My app work fine both the client and the server on the same machine, but when i try to access the service from other machine i got an exception timeout(the operation din not complete within the allotted timeout).The client reads some values throw the service from the database which is on the server.I don't know where is my mistake.I have tried to put the client in a virtual machine, and the service(and database) on the real machine.

Here is my Server config file:

            <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>

My client config file:

-->

            <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>

Thank you.

Those are the contracts: public interface ITrainServiceCallBack { [OperationContract (IsOneWay=true)] void OnTrainChangeState(TrainData train); }

//[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);
}

Method implementation:

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

namespace WCFandEFService { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ProductService" in both code and config file together. //[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);
            }
        });
    }






}

}

The operation contract(s) in the should be marked IsOneWay = true, and should return void - not all the operation contracts in the service.中的操作合同应标记为 IsOneWay = true,并且应返回无效 - 不是服务中的所有操作合同。

Also, I had a similar problem using duplex contracts over NetTcpBinding. I resolved this by setting the OperationTimeout value on the proxy (in my case, to 5 minutes). I set it programatically by casting my channel to the IContextChannel interface on the client when creating the channel. You should probably be able to do the same in the client config file.

My code:

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

Your endpoint address in the client and the server specifies "localhost" as the machine name. If they're in different machines, the client won't be able to talk to the service. Try changing it to the actual machine name where the server is located.

Update: here's an example of a WSDualHttpBinding working with non-one-way operations on both contract and callback contract. WSDualHttpBinding does not require that operations on the callback contract to be one way. PollingDuplexHttpBinding (for Silverlight) does, but that's another story.

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();
        }
    }
}

Check if you have marked your operation contract as one way. Its usual to get a timeout in dual http binding where people fail to mark the contract as one way.

[OperationContract(IsOneWay = true)]

EDIT

Please place the following line in the service contract's behavior.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 

For our reference, consider posting your service contract structure and the operation contract's implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM