I am struggling to achieve a requirement from the client.
I have a web service which in turn invokes client's webservice. Our service POST a request to the client service using UploadString() property of webclient.Here I have frequent requests to the client service,so I would like to keep the connection alive.I came to know that in HTTP 1.1 there is a feature called "KeepAlive" which allows persistent connection.My question is, is it possible to configure the timeout property of this keepalive via c# code?
Appreciate your help:)
To use that method, you must create a class derived from WebClient, see this example. You can set timeout, keepalive, tcpkeepalive also there. And use this class, instead of WebClient:
public class WebClientExtended : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
var w = (HttpWebRequest) base.GetWebRequest(uri);
w.Timeout = 5000; // Set timeout
w.KeepAlive = true; // Set keepalive true or false
w.ServicePoint.SetTcpKeepAlive(true, 1000, 5000); // Set tcp keepalive
return w;
}
}
Related
I am trying to use this as a commonly accepted solution for setting a timeouts for WeblClient calls. In my test case of requesting a url from an offline machine: I consistently get 20 second timeouts when set at 1 second.
public class TimeoutWebClient : WebClient
{
public TimeoutWebClient(TimeSpan timeout)
{
_timeout = timeout;
}
private TimeSpan _timeout;
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
request.Timeout = (int)_timeout.TotalMilliseconds;
return request;
}
}
Server based timeouts can't matter in this scenario. What could I be missing?
I did find a snippet that set both HttpWebRequest.ReadWriteTimeout and HttpWebRequest.ServicePoint.MaxIdleTime. But setting these to the timeout value still didn't make a difference and am still getting ~20 second timeouts.
Any other thoughts of what could cause this behavior?
Any chance you are using async download method?
From the MSDN:
The Timeout property affects only synchronous requests made with the GetResponse method. To time out asynchronous requests, use the Abort method.
When I do
RemotingServices.Marshal(foo, uri);
And the Client connects, everything works. When I wait for a few minutes and then try to connect the client, the Client throws a RemotingException: Object '{name of service}' has been disconnected or does not exist at the server.
What happens here? Is there a timeout of some sort?
To avoid timeouts, you can add to your remoted object the following overridden method:
public override object InitializeLifetimeService(){
return null;
}
If the website isn't responding after one second or so, it's probably safe to assume that it's a bad link and that I should move on to my next link in a set of "possible links."
How do I tell the WebClient to stop attempting to download after some predetermined amount of time?
I suppose I could use a thread, but if it's taking longer than one second to download, that's ok. I just want to make sure that it's connecting with the site.
Perhaps I should modify the WebClient headers, but I don't see what I should modify.
Perhaps I should use some other class in the System.Net namespace?
If you use the System.Net.WebRequest class you can set the Timeout property to be short and handle timeout exceptions.
try{
var request = WebRequest.Create("http://www.contoso.com");
request.Timeout = 5000; //set the timeout to 5 seconds
request.Method = "GET";
var response = request.GetResponse();
}
catch(WebException webEx){
//there was an error, likely a timeout, try another link here
}
Given an async controller:
public class MyController : AsyncController
{
[NoAsyncTimeout]
public void MyActionAsync() { ... }
public void MyActionCompleted() { ... }
}
Assume MyActionAsync kicks off a process that takes several minutes. If the user now goes to the MyAction action, the browser will wait with the connection open. If the user closes his browser, the connection is closed. Is it possible to detect when that happens on the server (preferably inside the controller)? If so, how? I've tried overriding OnException but that never fires in this scenario.
Note: I do appreciate the helpful answers below, but the key aspect of this question is that I'm using an AsyncController. This means that the HTTP requests are still open (they are long-lived like COMET or BOSH) which means it's a live socket connection. Why can't the server be notified when this live connection is terminated (i.e. "connection reset by peer", the TCP RST packet)?
I realise this question is old, but it turned up frequently in my search for the same answer.
The details below only apply to .Net 4.5
HttpContext.Response.ClientDisconnectedToken is what you want. That will give you a CancellationToken you can pass to your async/await calls.
public async Task<ActionResult> Index()
{
//The Connected Client 'manages' this token.
//HttpContext.Response.ClientDisconnectedToken.IsCancellationRequested will be set to true if the client disconnects
try
{
using (var client = new System.Net.Http.HttpClient())
{
var url = "http://google.com";
var html = await client.GetAsync(url, HttpContext.Response.ClientDisconnectedToken);
}
}
catch (TaskCanceledException e)
{
//The Client has gone
//you can handle this and the request will keep on being processed, but no one is there to see the resonse
}
return View();
}
You can test the snippet above by putting a breakpoint at the start of the function then closing your browser window.
And another snippet, not directly related to your question but useful all the same...
You can also put a hard limit on the amount of time an action can execute for by using the AsyncTimeout attribute. To use this use add an additional parameter of type CancellationToken. This token will allow ASP.Net to time-out the request if execution takes too long.
[AsyncTimeout(500)] //500ms
public async Task<ActionResult> Index(CancellationToken cancel)
{
//ASP.Net manages the cancel token.
//cancel.IsCancellationRequested will be set to true after 500ms
try
{
using (var client = new System.Net.Http.HttpClient())
{
var url = "http://google.com";
var html = await client.GetAsync(url, cancel);
}
}
catch (TaskCanceledException e)
{
//ASP.Net has killed the request
//Yellow Screen Of Death with System.TimeoutException
//the return View() below wont render
}
return View();
}
You can test this one by putting a breakpoint at the start of the function (thus making the request take more than 500ms when the breakpoint is hit) then letting it run out.
Does not Response.IsClientConnected work fairly well for this? I have just now tried out to in my case cancel large file uploads. By that I mean if a client abort their (in my case Ajax) requests I can see that in my Action. I am not saying it is 100% accurate but my small scale testing shows that the client browser aborts the request, and that the Action gets the correct response from IsClientConnected.
It's just as #Darin says. HTTP is a stateless protocol which means that there are no way (by using HTTP) to detect if the client is still there or not. HTTP 1.0 closes the socket after each request, while HTTP/1.1 can keep it open for a while (a keep alive timeout can be set as a header). That a HTTP/1.1 client closes the socket (or the server for that matter) doesn't mean that the client has gone away, just that the socket hasn't been used for a while.
There are something called COMET servers which are used to let client/server continue to "chat" over HTTP. Search for comet here at SO or on the net, there are several implementations available.
For obvious reasons the server cannot be notified that the client has closed his browser. Or that he went to the toilet :-) What you could do is have the client continuously poll the server with AJAX requests at regular interval (window.setInterval) and if the server detects that it is no longer polled it means the client is no longer there.
We will need to call out to a 3rd party to retrieve a value using REST, however if we do not receive a response within 10ms, I want to use a default value and continue processing.
I'm leaning towards using an asynchronous WebRequest do to this, but I was wondering if there was a trick to doing it using a synchronous request.
Any advice?
If you are doing a request and waiting on it to return I'd say stay synchronous - there's no reason to do an async request if you're not going to do anything or stay responsive while waiting.
For a sync call:
WebRequest request = WebRequest.Create("http://something.somewhere/url");
WebResponse response = null;
request.Timeout = 10000; // 10 second timeout
try
{
response = request.GetResponse();
}
catch(WebException e)
{
if( e.Status == WebExceptionStatus.Timeout)
{
//something
}
}
If doing async:
You will have to call Abort() on the request object - you'll need to check the timeout yourself, there's no built-in way to enforce a hard timeout.
You could encapsulate your call to the 3rd party in a WebService. You could then call this WebService synchronously from your application - the web service reference has a simple timeout property that you can set to 10 seconds or whatever.
Your call to get the 3rd party data from your WebService will throw a WebException after the timeout period has elapsed. You catch it and use a default value instead.
EDIT: Philip's response above is better. RIF.