WCF & keepAliveEnabled - More than two sockets at the same time? - c#

I try to make a multiple-thread requester in order to test answer time of my server.
My server is a WCF webservice, and my client has a service reference to this webservice.
WCF respect HTTP specifications, and I see on many websites WCF is Keep-Alive enabled by default. By only two connections from the same client are authorized at same time.
So, when I try to create 100 threads, only two of them are processing at the same time. So, after few loops, a lot of threads are in timeout.
I try to follow this article : WCF wsHttpBinding with http keepalive but it didn't work.
Here is my app config (modified by the Service Reference) :
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ISabIn" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xxx.xxx.xxx.xxx:xxx/SabIn.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ISabIn" contract="TestWs.ISabIn"
name="BasicHttpBinding_ISabIn" />
</client>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
I try to use customBinding in the appCode, like this article : HTTP Keep-alive and ServiceHost / C#?
but, when I execute my software, an erreor appears about "application/xml". If I try to translate in english, it would be somehting like "your client don't manage the application/xml message".
I need to do real-time transactions, and I can't if WCF only manage two sockets at same time...
Can you help me ?
PS : I can post the code of my client, but I'm not sure is useful since I know the problem is a sockets limitation.
SOLUTION (thnaks to Spender) : at the beginning of your code, change the default value (it is 2) in System.Net.ServicePointManager.DefaultConnectionLimit

Isn't this caused by default .net limits on HTTP request to a single host? This is because ServicePointManager.DefaultConnectionLimit defaults to 2.
When you issue an HTTP request, internally, a ServicePoint instance is created to manage the connections to a specific host. Make a new request to the same host, and it will use the same ServicePoint instance for connection management.
You can manipulate the limit for a single host with the following code:
var serviceUri = new Uri("http://xxx.xxx.xxx.xxx:xxx/SabIn.svc");
var servicePoint = System.Net.ServicePointManager.FindServicePoint(serviceUri);
servicePoint.ConnectionLimit = int.MaxValue;
I believe you can also handle this in web.config/app.config but I'm not sure if you can tweak limits associated with a single ServicePoint.

Related

WCF Request Delay Every 50 Seconds

I have a simple WCF service that streams images to the client. On the client, the first request for an image takes around 5.5 seconds and then subsequent requests take around 40ms, which is great.
However, after every ~45 seconds, regardless of whether any requests have been made the next request always takes around 4.6 seconds. This 45 second cycle repeats continuously.
I am using net.tcp binding with streamed transfer mode. I have also tried buffered transfer mode with/without reliable sessions enabled but all this did was increase the time taken for each request.
I have tried increasing each of the binding timeouts (open, close, send, receive, inactivity) with no change.
Server config:
serviceHost = new ServiceHost(typeof(TServiceImplementation), serviceUri);
serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = false });
var netTCPBinding = new NetTcpBinding(SecurityMode.Transport);
netTCPBinding.TransferMode = TransferMode.StreamedResponse;
netTCPBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
serviceHost.AddServiceEndpoint(typeof(TServiceContract), netTCPBinding, ServiceName);
serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
Client config:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="TcpBinding" transferMode="StreamedResponse" maxReceivedMessageSize="2147483647" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://hostname:9000/StreamService"
binding="netTcpBinding" bindingConfiguration="TcpBinding" contract="StreamService.IStream"
name="NetTcpBinding_IStream" />
</client>
</system.serviceModel>
UPDATE: It looks like this might be a machine specific issue - when I run the service on my local machine I do not experience this issue.
Ok, so a bit more investigation and I have determined that this was an address resolution issue - The actual images were hosted on a different machine to the one running the service so I changed the config to use the IP address of the host rather than the computer name and the problem was resolved.
I'm guessing this has something to do with a name cache timeout but not looked into which one it could be yet.

How to create a WCF that listens to TCP requests over web

I have a gps device that will send packets to TCP connection hosted over web that will have a static IP address & dedicated port for it.
My question is how to achieve it using WCF ? Or if WCF is needed or not for this problem.
Please help me. Thanx in advance.
Did you mean TCP embedded transported/embedded using http? or just TCP but using the internet?
The last is supported for sure.
To set a TCP connectionover WCF is easy, just use NetTcpBinding, you can set this in C# code or better in .config file like this:
<system.serviceModel>
<bindings>
<netTcpBinding name="portSharingBinding"
portSharingEnabled="true" />
</bindings>
<services>
<service name="MyService">
<endpoint address="net.tcp://localhost/MyService"
binding="netTcpBinding"
contract="IMyService"
bindingConfiguration="portSharingBinding" />
</service>
</services>
</system.serviceModel>
There's no differece between setup a TCP channel in a private network or in a public one (internet)
I strongly recommend You to read a A truely simple example to get started with TCP and WCF
Depending the type of data being sent you could use (in ascending order of abstraction):
Examples of use are given in the documentation.
TCP Listener:
https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx
HttpListner: https://msdn.microsoft.com/en-us/library/system.net.httplistener(v=vs.110).aspx
A nice example here: https://www.codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server.aspx
Or use a full framework like WebApi or Nancy.
http://www.asp.net/web-api
http://nancyfx.org/
Without knowing how you are wanting to send the data it is hard to recommend but don't reinvent the wheel if you don't have to.

Call Soap Service From a Windows Service

I am consuming a Soap service http://example.com/soap/webservice.php in my desktop application . i created a separate class library Included the service and used this class library to consume it in my main application which i working fine.
Here is the code i am using:
MyService.PushServerWSPortTypeClient obj = new MyService.PushServerWSPortTypeClient();
string result = obj.auth(apiId, UserName, Password);
This is working perfect.
But when i use this service in my windows service i am getting the exception:
There was no endpoint listening at http://exmaple.com/soap/webservice.php that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
I know what this exception means that it is unable to find endpoint of it in my service, but in my class library endpoints are mentioned in it's app.config and i also added these endpoints in my windows service app.config as well.
Here is the code from app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="PushServerWSBinding" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://example.com/soap/webservice.php"
binding="basicHttpBinding" bindingConfiguration="PushServerWSBinding"
contract="MyService.PushServerWSPortType" name="PushServerWSPort" />
</client>
</system.serviceModel>
Inner Exception Message :
The remote name could not be resolved: 'api.example.com'
Stack Trace :
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStream()
It is possible that your browser uses some proxy where your code does not (or use different one).
If it is the case make sure to set WebClient.Proxy property to match one in the browser, making use of the WebProxy class using
WebClient webClient = new WebClient())
{
webClient.Proxy = new WebProxy("myproxy.com");
result= webClient.DownloadString(someURL);
}
If not sure, try out his DNS-Testing link. It is unlikely, but possible if browser uses different DNS than your code.
After digging one complete day,Today we contacted our Networks Department for this weird issue and we came to know that When we use Desktop Application to call any SOAP or WCF Service the request goes through Proxy Server, but in the case of Windows Service the request goes through System Gateway/Firewall and on Firewall port 80 was blocked, due to which the request was unable to call server.
When we opened the port 80 for the service specific url it started wroking normally.

Newly created WCF Project in VS2012 doesnt have service node in WebConfigs

I have created a new WCF project using Visual Studio 2012,
I noticed that there is no Service node in the web.config to define the service and the contract, however i deployed the service to azure and it worked, however I`m getting this error:
The remote server returned an unexpected response: (413) Request Entity Too Large. In Silverlight
so i guess i need to increase the maximum allowed request but how do i do that with no service node ?
Beginning with VS 2010 WCF added the concept of default endpoints (as well as default bindings and behaviors), to simplify configuration.
The details can be found at this link: A Developer's Introduction to Window's Communication Foundation 4
In your case, you'll need to create a binding in your config file that has larger sizes, and either set that as the default binding or assign that binding to an explicitly defined endpoint.
By default WCF (in .NET 4+) will assign request coming in over http to basicHttpBinding. These protocol mappings can also be changed in the config file.
A couple of simple examples to help you (the article I linked goes into more detail):
To create a default binding, simply define the binding and omit the name attribute:
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="10000000" ....>
</basicHttpBinding>
</bindings>
This will make your supplied configuration the default basicHttpBinding for the service(s) using that config.
Alternatively, you can use the name attribute on a binding configuration and then assign it to an defined input. Let's say you have a binding name "MyBinding":
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="MyBinding"
contract="MyService.IMyContract" />
If you want something other than basicHttpBinding for http requests, you can do this in the protocols section:
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="wsHttpBinding" bindingConfiguration="" />
The key in your situation is to you'll need to create the binding with larger values, and then either set it as the default or assign it to an endpoint (which you'll also need to define).
As I said, these are just simple examples to give you an idea, and there's a lot more detail in the article I linked.

I need to develop a WCF service that will only be exposed thru HTTP/HTTPS. How to use HTTP cookies?

First of all, I admit I'm a newbie in WCF. Still not out of the training wheels.
I was assigned to develop a WCF service, and part of the requirements is that a sort of "session token" needs to be passed with each request as an HTTP cookie. (Predictably, such token needs be generated in the HTTP response headers of a successful "logon" call in such service).
Is this straightforward?
Disclaimer: you're not really supposed to do any of this, because it's forcing a WCF service to behave as a web service. But if you need cookies, read on.
If all you need is the session id, you can get it from:
OperationContext.Current.SessionId
If you need cookies, you'll need to jump through some hoops. The gist of it is (1) set asp.net compatibility, and (2) reference HttpContext.Current properties.
Your service will need to use a wsHttpBinding (or another binding that supports sessions). If create your project to be a WCF service hosted in IIS, you'll get these by default. You'll also need to set asp.net compatibility in the config file.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="MyBinding" allowCookies="false" ... </binding>
</wsHttpBinding>
</bindings>
(see the link here for why I have allowCookies=false)
To enable sessions, on your WCF Service Contract, set the following
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IMyWcfService {...}
You may also want to set the ServiceBehavior on the service itself (PerSession is the default), and you'll need to set asp.net compatibility.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
public class MyWcfService : IMyWcfService {...}
Some relevant properties you then have access to:
// Gives you the current session id as a string
HttpContext.Current.Session.SessionID
// Indicates whether the service is using sessionless cookies
HttpContext.Current.Session.CookieMode
// Indicates whether the session id is stored in the url or in an HTTP cookie
HttpContext.Current.Session.IsCookieless
// The cookies themselves
HttpContext.Current.Request.Cookies
HttpContext.Current.Response.Cookies
// The session and cache objects
HttpContext.Current.Cache
HttpContext.Current.Session
A link on sessions in WCF Services:
http://msdn.microsoft.com/en-us/library/ms733040.aspx
HTH,
James
This topic on msdn could help you out http://msdn.microsoft.com/en-us/library/bb398778.aspx.
Also, this could help you out with hosting you`r WCF service inside IIS: http://msdn.microsoft.com/en-us/library/aa702682.aspx
and http://msdn.microsoft.com/en-us/library/bb332338.aspx (Hosting Using Internet Information Services)
This just answers your question partially, but will give you a head start with config.
In your config file under the service config section, create basic http bindings like that:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="myHttpBinding" allowCookies="true">
</binding>
</basicHttpBinding>
</system.serviceModel>
Then read up on wcf binding and endpoints configuration.

Categories