连续流媒体网站上的 .NET HTTP 请求超时不是 "Aborting"
.NET HTTP Request Timeout not "Aborting" on continuous streaming site
范围
我已经为 Http Web Request class 开发了一个 Wrapper,以更简单的方式执行 Gets 和 Posts。这个库已经使用了两年多没有任何问题,但是今天,我们遇到了一个奇怪的问题。
有 one website(加载需要一段时间),显然,它一直在向 HTML 前端传输字符,所以我们的库 "Get" 请求陷入循环.
不同的超时属性
查看 Http Web 请求参考,我们发现有两个不同的 timeout
属性。我们正在使用它们,但它们似乎都无法正常中止。
- Read Write Timeout - 获取或设置写入流或从流读取时的超时时间(以毫秒为单位)。
- Timeout - 获取或设置 GetResponse 和 GetRequestStream 方法的超时值(以毫秒为单位)。
一个超时来统治他们
有没有什么方法可以设置一个 "Operation Timeout" 来强制 stream/connection 在预先配置的时间后进行处理?
一些代码示例
public class Program
{
public static void Main()
{
string url = "http://anus.io";
Console.WriteLine("Initializing Request State Object");
RequestState myRequestState = new RequestState();
// Creating Http Request
myRequestState.request = (HttpWebRequest)WebRequest.Create(url);
myRequestState.request.Method = "GET";
myRequestState.request.ReadWriteTimeout = 4000;
myRequestState.request.Timeout = 4000;
Console.WriteLine("Begining Async Request");
IAsyncResult ar = myRequestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), myRequestState);
Console.WriteLine("Waiting for Results");
ar.AsyncWaitHandle.WaitOne();
myRequestState.response = (HttpWebResponse)myRequestState.request.EndGetResponse(ar);
Console.WriteLine("Response status code = {0}", myRequestState.response.StatusCode);
}
public static void ResponseCallback (IAsyncResult asyncResult)
{
Console.WriteLine("Completed");
}
}
This Code seem to work fine,但是我如何将响应读取为字符串,因为它一直在传输(如浏览器所示)?
问题
处理此类网站的正确方法是什么? (我所说的句柄是指能够识别和跳过服务器不会停止传输的情况?)
试试这个:
public static void Main()
{
string url = "http://anus.io";
***int DefaultTimeOut = 15000;*** //timeout after 15 sec
Console.WriteLine("Initializing Request State Object");
RequestState myRequestState = new RequestState();
// Creating Http Request
myRequestState.request = (HttpWebRequest)WebRequest.Create(url);
myRequestState.request.Method = "GET";
myRequestState.request.ReadWriteTimeout = 4000;
myRequestState.request.Timeout = 4000;
Console.WriteLine("Begining Async Request");
IAsyncResult ar = myRequestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), myRequestState);
***ThreadPool.RegisterWaitForSingleObject(ar.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myRequestState.request, DefaultTimeOut, true);***
Console.WriteLine("Waiting for Results");
ar.AsyncWaitHandle.WaitOne();
try{
myRequestState.response = (HttpWebResponse)myRequestState.request.EndGetResponse(ar);
Console.WriteLine("Response status code = {0}", myRequestState.response.StatusCode);
}catch(Exception){
Console.WriteLine("Request Aborted");
}
}
public static void ResponseCallback (IAsyncResult asyncResult)
{
Console.WriteLine("Completed");
}
//call the timeout if more than 15 seconds
**public static void TimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
}**
我会将整个 HTTP 处理移动到 Task
中,并使用通用技术为该任务设置超时。许多此类技术都可用。
我不明白你为什么需要这么多的个人超时。你能不能直接说:如果这个请求超过4秒,不管什么原因,杀掉它。
APM 模式和等待事件是 .NET 4.5 和 C# 5 时代的危险信号。所有这些垃圾都掩盖了代码的意图。如果您使用 await
来使用 WebRequest
class 提供的异步 IO 并使用围绕它的通用超时技术,那么垃圾就会消失。
范围
我已经为 Http Web Request class 开发了一个 Wrapper,以更简单的方式执行 Gets 和 Posts。这个库已经使用了两年多没有任何问题,但是今天,我们遇到了一个奇怪的问题。
有 one website(加载需要一段时间),显然,它一直在向 HTML 前端传输字符,所以我们的库 "Get" 请求陷入循环.
不同的超时属性
查看 Http Web 请求参考,我们发现有两个不同的 timeout
属性。我们正在使用它们,但它们似乎都无法正常中止。
- Read Write Timeout - 获取或设置写入流或从流读取时的超时时间(以毫秒为单位)。
- Timeout - 获取或设置 GetResponse 和 GetRequestStream 方法的超时值(以毫秒为单位)。
一个超时来统治他们
有没有什么方法可以设置一个 "Operation Timeout" 来强制 stream/connection 在预先配置的时间后进行处理?
一些代码示例
public class Program
{
public static void Main()
{
string url = "http://anus.io";
Console.WriteLine("Initializing Request State Object");
RequestState myRequestState = new RequestState();
// Creating Http Request
myRequestState.request = (HttpWebRequest)WebRequest.Create(url);
myRequestState.request.Method = "GET";
myRequestState.request.ReadWriteTimeout = 4000;
myRequestState.request.Timeout = 4000;
Console.WriteLine("Begining Async Request");
IAsyncResult ar = myRequestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), myRequestState);
Console.WriteLine("Waiting for Results");
ar.AsyncWaitHandle.WaitOne();
myRequestState.response = (HttpWebResponse)myRequestState.request.EndGetResponse(ar);
Console.WriteLine("Response status code = {0}", myRequestState.response.StatusCode);
}
public static void ResponseCallback (IAsyncResult asyncResult)
{
Console.WriteLine("Completed");
}
}
This Code seem to work fine,但是我如何将响应读取为字符串,因为它一直在传输(如浏览器所示)?
问题
处理此类网站的正确方法是什么? (我所说的句柄是指能够识别和跳过服务器不会停止传输的情况?)
试试这个:
public static void Main()
{
string url = "http://anus.io";
***int DefaultTimeOut = 15000;*** //timeout after 15 sec
Console.WriteLine("Initializing Request State Object");
RequestState myRequestState = new RequestState();
// Creating Http Request
myRequestState.request = (HttpWebRequest)WebRequest.Create(url);
myRequestState.request.Method = "GET";
myRequestState.request.ReadWriteTimeout = 4000;
myRequestState.request.Timeout = 4000;
Console.WriteLine("Begining Async Request");
IAsyncResult ar = myRequestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), myRequestState);
***ThreadPool.RegisterWaitForSingleObject(ar.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myRequestState.request, DefaultTimeOut, true);***
Console.WriteLine("Waiting for Results");
ar.AsyncWaitHandle.WaitOne();
try{
myRequestState.response = (HttpWebResponse)myRequestState.request.EndGetResponse(ar);
Console.WriteLine("Response status code = {0}", myRequestState.response.StatusCode);
}catch(Exception){
Console.WriteLine("Request Aborted");
}
}
public static void ResponseCallback (IAsyncResult asyncResult)
{
Console.WriteLine("Completed");
}
//call the timeout if more than 15 seconds
**public static void TimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
}**
我会将整个 HTTP 处理移动到 Task
中,并使用通用技术为该任务设置超时。许多此类技术都可用。
我不明白你为什么需要这么多的个人超时。你能不能直接说:如果这个请求超过4秒,不管什么原因,杀掉它。
APM 模式和等待事件是 .NET 4.5 和 C# 5 时代的危险信号。所有这些垃圾都掩盖了代码的意图。如果您使用 await
来使用 WebRequest
class 提供的异步 IO 并使用围绕它的通用超时技术,那么垃圾就会消失。