我目前正在使用使用HttpClient类发出HTTP请求的代码。虽然您可以为请求指定超时,但该值适用于整个请求(包括解析主机名,建立连接,发送请求和接收响应)。
如果无法解析名称或建立连接,我需要一种方法让请求快速失败,但我有时也需要接收大量数据,因此不能只是减少超时。
有没有办法使用内置(BCL)类或备用HTTP客户端堆栈实现此目的?
我已经简要地看了一下RestSharp和ServiceStack,但似乎都没有为连接部分提供超时(但如果我错了,请纠正我)。
答案 0 :(得分:5)
如果连接花费太多时间,您可以使用Timer
中止请求。在经过时间后添加事件。你可以使用这样的东西:
static WebRequest request;
private static void sendAndReceive()
{
// The request with a big timeout for receiving large amout of data
request = HttpWebRequest.Create("http://localhost:8081/index/");
request.Timeout = 100000;
// The connection timeout
var ConnectionTimeoutTime = 100;
Timer timer = new Timer(ConnectionTimeoutTime);
timer.Elapsed += connectionTimeout;
timer.Enabled = true;
Console.WriteLine("Connecting...");
try
{
using (var stream = request.GetRequestStream())
{
Console.WriteLine("Connection success !");
timer.Enabled = false;
/*
* Sending data ...
*/
System.Threading.Thread.Sleep(1000000);
}
using (var response = (HttpWebResponse)request.GetResponse())
{
/*
* Receiving datas...
*/
}
}
catch (WebException e)
{
if(e.Status==WebExceptionStatus.RequestCanceled)
Console.WriteLine("Connection canceled (timeout)");
else if(e.Status==WebExceptionStatus.ConnectFailure)
Console.WriteLine("Can't connect to server");
else if(e.Status==WebExceptionStatus.Timeout)
Console.WriteLine("Timeout");
else
Console.WriteLine("Error");
}
}
static void connectionTimeout(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("Connection failed...");
Timer timer = (Timer)sender;
timer.Enabled = false;
request.Abort();
}
这里的时间只是例如,你必须根据自己的需要进行调整。
答案 1 :(得分:2)
.NET的HttpWebRequest公开了2个属性,用于指定与远程HTTP服务器连接的超时:
Timeout
属性最接近您所追求的属性,但它确实表明无论超时值如何,DNS解析最多可能需要15秒:
域名系统(DNS)查询最多可能需要15秒才能返回或超时。如果您的请求包含需要解析的主机名,并且您将Timeout设置为小于15秒的值,则可能需要15秒或更长时间才会抛出WebException以指示请求超时。
为DNS查找提取低于15秒的超时的一种方法是lookup the hostname yourself,但许多解决方案需要P / Invoke来指定低级设置。
还可以在ServiceStack的高级HTTP客户端中指定基础HttpWebRequest
超时和 ReadWriteTimeout 属性,即在C# Service Clients中使用:< / p>
var client = new JsonServiceClient(BaseUri) {
Timeout = TimeSpan.FromSeconds(30)
};
或使用ServiceStack的HTTP Utils:
var timeoutMs = 30 * 1000;
var response = url.GetStringFromUrl(requestFilter: req =>
req.Timeout = timeoutMs);
答案 2 :(得分:1)
我相信RestSharp在RestClient中确实有超时属性。
var request = new RestRequest();
var client = new RestClient
{
Timeout = timeout, //Timeout in milliseconds to use for requests made by this client instance
ReadWriteTimeout = readWriteTimeout //The number of milliseconds before the writing or reading times out.
};
var response = client.Execute(request);
//Handle response
答案 3 :(得分:0)
你没错,你无法设置这个特定的超时。 我没有足够的信息来了解这些库是如何构建的,但是出于它们的目的,我相信它们是合适的。有人想做一个请求并为所有事情设置超时。
我建议你采取不同的方法。
你试图在HttpRequest
同时做两件不同的事情:
您可以尝试将其分为两个阶段。
Ping
类(check this out)尝试访问主机并为其设置超时时间; HttpRequest
IF (超时,这个过程不应该减慢一切,因为解析名称/路线的一部分将在第一阶段完成。这不是完全一次性的。
此解决方案存在一个缺点:您的远程主机必须接受ping。 希望这会有所帮助。
答案 4 :(得分:0)
我使用此方法检查是否可以建立连接。但是,这并不能保证可以通过HttpWebRequest
中的后续呼叫建立连接。
private static bool CanConnect(string machine)
{
using (TcpClient client = new TcpClient())
{
if (!client.ConnectAsync(machine, 443).Wait(50)) // Check if we can connect in 50ms
{
return false;
}
}
return true;
}
答案 5 :(得分:-1)
如果超时不符合您的需要 - 请勿使用它们。您可以使用等待操作完成的处理程序。当你得到一个回应 - 停止处理程序并继续。这样,当失败和长时间请求大量数据时,您将获得短时间请求。
这样的事情可能是:
var handler = new ManualResetEvent(false);
request = (HttpWebRequest)WebRequest.Create(url)
{
// initialize parameters such as method
}
request.BeginGetResponse(new AsyncCallback(delegate(IAsyncResult result)
{
try
{
var request = (HttpWebRequest)result.AsyncState;
using (var response = (HttpWebResponse)request.EndGetResponse(result))
{
using (var stream = response.GetResponseStream())
{
// success
}
response.Close();
}
}
catch (Exception e)
{
// fail operations go here
}
finally
{
handler.Set(); // whenever i succeed or fail
}
}), request);
handler.WaitOne(); // wait for the operation to complete
答案 6 :(得分:-1)
如果首先只询问标题,那么如果成功请求通常的资源
webRequest.Method = "HEAD";