【发布时间】:2017-08-09 02:39:12
【问题描述】:
我的 HttpClient 使用摘要身份验证连接到服务器并期望搜索查询作为响应。这些搜索查询可以随时出现,因此客户端应始终保持连接打开。
使用以下代码建立连接:
public static async void ListenForSearchQueries(int resourceId)
{
var url = $"xxx/yyy/{resourceId}/waitForSearchRequest?token=abc";
var httpHandler = new HttpClientHandler { PreAuthenticate = true };
using (var digestAuthMessageHandler = new DigestAuthMessageHandler(httpHandler, "user", "password"))
using (var client = new HttpClient(digestAuthMessageHandler))
{
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
var request = new HttpRequestMessage(HttpMethod.Get, url);
var tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(TimeSpan.FromMilliseconds(Timeout.Infinite));
using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, tokenSource.Token))
{
Console.WriteLine("\nResponse code: " + response.StatusCode);
using (var body = await response.Content.ReadAsStreamAsync())
using (var reader = new StreamReader(body))
while (!reader.EndOfStream)
Console.WriteLine(reader.ReadLine());
}
}
}
这是在控制台应用程序的 Main 方法中使用该方法的方式。
private static void Main(string[] args)
{
const int serviceId = 128;
.
.
.
ListenForSearchQueries(resourceId);
Console.ReadKey();
}
控制台窗口的输出如下所示:
Response code: OK
--searchRequestBoundary
即使客户端的超时设置为无穷大,在第一次输出后大约五分钟后连接超时(这不是 HttpClient 的默认超时),并抛出以下异常。
System.IO.IOException occurred
HResult=0x80131620
Message=The read operation failed, see inner exception.
Source=System.Net.Http
StackTrace:
at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Http.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.get_EndOfStream()
at ConsoleTester.Program.<ListenSearchQueriesDigestAuthMessageHandler>d__10.MoveNext() in C:\Users\xyz\ProjName\ConsoleTester\Program.cs:line 270
Inner Exception 1:
WebException: The operation has timed out.
用于身份验证的 DelegateHandler 是对this 代码的粗略改编(参见源代码部分)。
为什么客户端会超时?如何防止这种情况发生?
我的最终目标是拨打电话并无限期地等待回复。当响应确实到来时,我不希望连接关闭,因为将来可能会出现更多响应。不幸的是,我无法在服务器端更改任何内容。
【问题讨论】:
-
避免使用
async void。此方法应使用Task定义。还要展示这个方法是如何被调用的。 -
这似乎是XY problem。您要达到的最终目标是什么?
-
@Nkosi 该方法在控制台应用程序的 main 方法中调用如下:
ListenForSearchQueries(resourceId); Console.ReadKey(); -
async void 着火了,忘记这可能是导致您的问题的原因。您需要使该方法返回一个任务并在该任务上调用等待。更新问题以显示主要方法。
-
您是否有其他客户端以这种方式与服务器通信的工作示例?也许是服务器本身附带的东西?我想知道超时是否是由您根本无法控制的 httpclient 的依赖引起的。甚至可能是操作系统将超时作为资源管理策略。如果超时发生在可预测的时间段之后,但仍小于您为超时指定的时间,那肯定会指向您能够控制的 httpclient 中的逻辑以外的其他内容。
标签: c# http dotnet-httpclient