服务器在写入响应头后关闭连接导致 HttpClient 异常

6

我正在使用HttpClient通过PutAsync将数据放到HTTP服务器上。

当服务器返回错误代码(例如401 Unauthorized)时,它会关闭连接(在响应中提供Connection: close头)。此时,HttpClient会抛出System.Net.Http.HttpRequestException(在将内容复制到流中时出错),并列出以下内部异常。这似乎与写出数据有关(尽管它在BeginRead中),因为如果我说服服务器读取发送的所有数据,则不会引发异常。

我可以通过使用HttpClient.SendAsync执行相同任务,并使用HttpCompletionOption.ResponseHeadersRead参数来解决问题。在这种情况下,不会引发异常,我可以读取HttpResponseMessage.StatusCode

我的问题是,这个异常正确吗?即服务器是否没有遵循关闭连接之前读取所有数据的标准?如果不是,那么PutAsync是否存在问题,因为它在这种情况下不允许访问返回的StatusCode

示例代码:

using (FileStream stream = File.OpenRead(FilePath))
using (StreamContent content = new StreamContent(stream))
using (HttpRequestMessage req = new HttpRequestMessage
    {
        Method = HttpMethod.Put,
        RequestUri = new Uri(baseUri, Path),
        Content = content,
    })
using (HttpClient client = new HttpClient())
{
    req.Content.Headers.ContentType = new MediaTypeHeaderValue(FileContentType);
    // This version works:
    //using (HttpResponseMessage resp = await client.SendAsync(req,
    //    HttpCompletionOption.ResponseHeadersRead))
    // This version throws an exception:
    using (HttpResponseMessage resp = await client.PutAsync(
        new Uri(baseUri, Path), content))
    {
        if (resp.StatusCode == HttpStatusCode.Unauthorized)
        {
            // Try again with authorisation credentials based on resp.Headers.WwwAuthenticate
        }
    }
}

内部异常:System.IO.IOException(无法从传输连接中读取数据:远程主机强制关闭了现有的连接。)

at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.PooledStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.ConnectStream.BeginReadWithoutValidation(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.ConnectStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
at System.Net.Http.StreamToStreamCopy.StartRead()

带有内部异常: System.Net.Sockets.SocketException(远程主机强制关闭了一个现有的连接)

at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
1个回答

0

如果符合您的需求,请尝试使用HTTP协议版本1.0:

using (HttpRequestMessage req = new HttpRequestMessage
    {
        Method = HttpMethod.Put,
        RequestUri = new Uri(baseUri, Path),
        Content = content,
        Version = HttpVersion.Version10
    })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接