Environment
There is WCF Service (NET:TCP | Reliable | SecurityEnabled) running as console on Physical Machine A
There are 20-30 .NET client applications (Winforms) exposed over Citrix so hosted again on One physical machine different from server.
Problem
The application structure follows the same pattern as discussed in http://msdn.microsoft.com/en-us/magazine/cc163537.aspx by Juval Lowy.
The problem is at the server it is able to invoke the callback with no errors, but the client never receives it. There is code tries to subscribe again if no callback call within 60secs. It has a side effect that it opens a new connection by calling Subscribe API on the server. Over a period you can see many TCP connections open on the server. No errors but still client callback is never invoked.
Additional Information
Sometimes following error is thrown:
The message could not be transferred within the allotted timeout of 00:01:00. There was no space available in the reliable channel's transfer window. The time allotted to this operation may have been a portion of a longer timeout.
In addition MaxBufferPoolSize is set to Int64.MaxValue as you can see in the code below
var binding = new NetTcpBinding(SecurityMode.Transport, reliableSession);
binding.ReliableSession.Enabled = true;
binding.ReliableSession.InactivityTimeout = TimeSpan.FromDays(1);
binding.ReliableSession.Ordered = true;
binding.CloseTimeout = TimeSpan.FromHours(1);
binding.SendTimeout = TimeSpan.FromHours(1);
binding.ReceiveTimeout = TimeSpan.FromHours(1);
binding.OpenTimeout = TimeSpan.FromHours(1);
binding.ReaderQuotas.MaxDepth = Int32.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
binding.ReaderQuotas.MaxBytesPerRead = Int32.MaxValue;
binding.ReaderQuotas.MaxNameTableCharCount = Int32.MaxValue;
binding.MaxBufferPoolSize = Int64.MaxValue;
binding.MaxReceivedMessageSize = Int32.MaxValue;
Any suggestions will be great help!
Recent findings:
I recently discovered the callback on the client side has different kinds of processing based on what is visible on the user screen. This was blocking the callbacks to be acknowledged. That explains the buffer overflow as well. The frequency of notifications sent from the server is very high compared to the time taken by each client to process them.
Apart from the changes I did like disabling security, configuring timeouts correctly, following line of code helped a lot:
public void OnNotification(AmigoMessage messsage)
{
ThreadPool.QueueUserWorkItem((x) => { ProcessNotification(messsage); });
}
Take a look at [CallbackBehavior(UseSynchronizationContext = false)]. Not having this attribute on the callback service will try to marshal to (usually) the UI thread.
Related
Usually when I consume a web service I add a service reference, put in the URL for the WSDL, and then finagle my way through the API's.
This time around I get a FaultException with the message: "Invalid security header".
Here is my binding:
CustomBinding bindingBNP = new CustomBinding();
SecurityBindingElement securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128;
securityElement.KeyEntropyMode = System.ServiceModel.Security.SecurityKeyEntropyMode.CombinedEntropy;
securityElement.IncludeTimestamp = false;
securityElement.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
MtomMessageEncodingBindingElement mtomElement = new MtomMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8);
HttpsTransportBindingElement httpsElement = new HttpsTransportBindingElement();
httpsElement.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
httpsElement.BypassProxyOnLocal = false;
httpsElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
httpsElement.ManualAddressing = false;
httpsElement.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
httpsElement.TransferMode = TransferMode.Buffered;
httpsElement.UnsafeConnectionNtlmAuthentication = false;
httpsElement.RequireClientCertificate = false;
httpsElement.UseDefaultWebProxy = false;
bindingBNP.Elements.Add(securityElement);
bindingBNP.Elements.Add(mtomElement);
bindingBNP.Elements.Add(httpsElement);
Related question: for diagnostic purposes, how do I know what the inbound/outbound communication is?
Fiddler doesn't seem to pick up anything (I guess it would have to be on the server machine, which I'm probably not going to be able to negotiate). WCF tracing only seems to surface communication "milestones" (if that word connotates some flavor of victory I am ways off!).
Fiddler runs on the client:
Did you start Fiddler before your client?
Did you configure your application to proxy its traffic?
Are you sure your WCF is using HTTP as the transport?
I'm fairly recent to WCF and trying to figure out the best way to accomplish my requirements.
I have an application hosting a WCF service with the following code:
Uri u1 = new
Uri("http://localhost:8732/Client1/WcfServiceLibrary1/Service1/"); Uri
u2 = new
Uri("http://localhost:8732/Client1/WcfServiceLibrary1/Service1/mex");
WSHttpBinding binding = new WSHttpBinding();
sHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1), u1);
ServiceMetadataBehavior meta = new ServiceMetadataBehavior();
meta.HttpGetEnabled = true;
sHost.AddServiceEndpoint(typeof(WcfServiceLibrary1.IService1), binding, u1);
sHost.Description.Behaviors.Add(meta); sHost.Open();
I can create a service reference on a client application and call methods on this service no problems. using the code below.
remoteService.Service1Client client = new remoteService.Service1Client();
remote.Text = client.GetData(3);
I can also call a method without a service reference.
EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8732/Client1/WcfServiceLibrary1/Service1/");
WSHttpBinding myBinding = new WSHttpBinding();
ChannelFactory<IService1> ServiceConnectionFactory = new ChannelFactory<IService1>(myBinding, myEndpoint);
IService1 serviceConnection = ServiceConnectionFactory.CreateChannel();
If I try to execute the same code in the host application it get the error below.
The request channel timed out while waiting for a reply after
00:01:00. Increase the timeout value passed to the call to Request or
increase the SendTimeout value on the Binding. The time allotted to
this operation may have been a portion of a longer timeout.
How can a application consume and use a WCF service that it is currently hosting? Do I need to open the service in a thread of its own?
The idea is for the host to trigger some initialization before clients connect.
I have a WCF service that implements the 'Custom-Username-Password-Validator'.
The service itself checks the username+password against a local file,
and if there is no match - it throws a FaultException with a message.
.
When I use the service synchronously it works fine.
When I go to work with it ASYNC, I have a problem.
If I pass the wrong 'Username+Password' credentials - and open the client,
instead of returning immediatly from the service going into my 'Channel_Faulted()' method,
the client thread simply waits until the Timeout triggers,
and then I get a 'TimeoutException'.
try
{
client = new MyServiceClient("WSDualHttpBinding_IMyervice");
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "bad password";
client.ChannelFactory.Faulted += new EventHandler(ChannelFactory_Faulted);
client.Open(); // This hangs for 01:00:00 minute
// Doesn't reach here
client.DoSomethingCompleted += new EventHandler<DoSomethingEventArgs(client_DoSomethingCompleted);
client.DoSomethingAsync(param);
}
catch (Exception ex)
{
// Enters here with a 'TimeoutException' exception
}
why does the client not trigger the 'Faulted' method I have ?
Why does it wait for a response from the service even though the service through a 'FaultException' during the 'Validate' method of the 'CustomUserNameValidator' ?
Sure, the code you are using appears to be missing 3 lines after your code line:
client.ChannelFactory.Faulted += new EventHandler(ChannelFactory_Faulted);
But again, I'm taking a shot in the dark since I've not made use of this option yet.
var local = client.ChannelFactory.CreateChannel();
((IClientChannel)local).Faulted += ChannelFaulted;
local.Open();
Better yet, the open method doesn't appear to be necessary according to the sample provide here: ChannelFactory
I personally have not used the ChannelFactory.Faulted event handler however, here is a post for your consideration: creating-wcf-channelfactory
While trying to build a client-server WCF application in Mono we ran into some issues.
Reducing it to just a bare example we found that the service only accepts one client at a time. If another client attempts to connect, it hangs until the first one disconnects.
Simply changing to BasicHttpBinding fixes it but we need NetTcpBinding for duplex communication. Also the problem does not appear if compiled under MS .NET.
EDIT: I doubt (and hope not) that Mono doesn't support what I'm trying to do. Mono code usually throws NotImplementedExceptions in such cases as far as I noticed. I am using Mono v2.6.4
This is how the service is opened in our basic scenario:
public static void Main (string[] args)
{
var binding = new NetTcpBinding ();
binding.Security.Mode = SecurityMode.None;
var address = new Uri ("net.tcp://localhost:8080");
var host = new ServiceHost (typeof(Hello));
host.AddServiceEndpoint (typeof(IHello), binding, address);
ServiceThrottlingBehavior behavior = new ServiceThrottlingBehavior ()
{
MaxConcurrentCalls = 100,
MaxConcurrentSessions = 100,
MaxConcurrentInstances = 100
};
host.Description.Behaviors.Add (behavior);
host.Open ();
Console.ReadLine ();
host.Close ();
}
The client channel is obtained like this:
var binding = new NetTcpBinding ();
binding.Security.Mode = SecurityMode.None;
var address = new EndpointAddress ("net.tcp://localhost:8080/");
var client = new ChannelFactory<IHello> (binding, address).CreateChannel ();
As far as I know this is a Simplex connection, isn't it?
The contract is simply:
[ServiceContract]
public interface IHello
{
[OperationContract]
string Greet (string name);
}
Service implementation has no ServiceModel tags or attributes.
I'll update with details as required.
I've played around with this a bit, and it definitely looks like a Mono bug.
I'm porting a WCF application to run in Mono at the moment. I had played with some NetTcpBinding stuff, but I hadn't tried this scenario (multiple connections to a Mono-hosted service host). However now I try it out, I'm able to reproduce - both in 2.6 and the latest daily package.
It does work in .NET, however. Any difference in behavior between Mono and .NET is classed as a bug. You should log it on Bugzilla with a test case, I would also post in the Mono newslist.
Good luck.
Definately a bug. I'm wondering if there was a version it was working correctly...
I've posted it at Novell Bugzilla, if you are interested in its progress.
I have a wcf service I am setting up to run under IIS 7. I have the service set to streaming for the transfermode.
When I self host the service in a console application every thing seems to work ok. But when the client connects to an iis hosted service it seems to be buffering, and the client eventual times out. I have used fiddler to determine that this client time out happens before the http request is even made.
Here is the servers binding.
var binding = new CustomBinding();
binding.Elements.Add( new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Soap12WSAddressing10
} );
var secBinding = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
secBinding.AllowInsecureTransport = true;
binding.Elements.Add( secBinding );
binding.Elements.Add( new HttpTransportBindingElement()
{
TransferMode = TransferMode.Streamed,
MaxReceivedMessageSize = Int32.MaxValue,
} );
And the client binding:
var binding = new CustomBinding();
binding.Elements.Add( new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Soap12WSAddressing10
} );
var secBinding = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
secBinding.AllowInsecureTransport = true;
binding.Elements.Add( secBinding );
binding.Elements.Add( new HttpTransportBindingElement()
{
TransferMode = TransferMode.Streamed,
MaxReceivedMessageSize = Int32.MaxValue,
MaxBufferSize = 400
} );
As an aside the connection is timing out because the stream is infinite and the server should read the first few bytes and then close the stream.
Recently, we had the same issue. When you host your service under IIS, no matter if you enable streaming or not, your service will buffer the entire message prior to sending it. The reason for this, is that it appears as though WCF does not set the Response.BufferOutput to "false" (default is true), when streaming is enabled on a service. A workaround can be found here:
http://weblogs.asp.net/jclarknet/archive/2008/02/14/wcf-streaming-issue-under-iis.aspx
Are you closing the Stream in the client? If true, try closing just in the service side.
Also, verify if its a OneWay operation.
Can you post the both binding nodes, for the endpoints?