我正在开发一个以将多张照片上传到网络API为中心的移动应用。我使用Xamarin.Forms和System.Net.Http.HttpClient,以及Clumsy来模拟不良网络状况(滞后,丢包,无序数据包)。该应用程序最初是用Titanium编写的,并且对大多数用户来说都很好,但是一些移动网络不佳的用户却经常出错。展望未来,我们正在移植到Xamarin并试图接纳连接不良的用户。
using (var httpClient = CreateClient())
{
httpClient.Timeout = TimeSpan.FromMinutes(5);
using (var formData = new MultipartFormDataContent())
{
// add required fields via formData.Add() ...
var httpContent = new ByteArrayContent(imageData);
formData.Add(httpContent, "file", Guid.NewGuid() + ".jpg");
try
{
var response = await httpClient.PostAsync("fileupload", formData).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
responseObject = await ResponseMessageToResponseModel(response).ConfigureAwait(false);
}
}
catch (HttpRequestException ex)
{
Debug.WriteLine("HttpRequestException");
}
catch (TaskCanceledException ex)
{
Debug.WriteLine("TaskCanceledException");
}
}
}
我发现的是,在正常情况下,一切都按预期工作;当使用"延迟,丢弃,无序"启用Clumsy时并尝试上传PostAsync()永远不会完成,并最终超时与TaskCanceledException。奇怪的是文件最终在服务器上..所以POST数据显然已经通过了。
我猜测从服务器响应中丢弃的数据包意味着HttpClient从未收到正确的响应并继续等待一个直到它超时。
为了达到这一点,我想知道是否有人对如何使这个过程尽可能防弹有任何想法。只是捕获超时并再次尝试,如果文件第一次完成,则不能很好地工作。有什么想法吗?
此外,关于HttpClient如何处理丢弃/无序数据包的任何信息,以便我可以更好地理解发生的事情也会很好。
答案 0 :(得分:1)
HttpClient的一件事我不久前撞了我的脑袋是对POST请求的特殊处理(读取不常见)。
发送POST请求时,它首先将标头(包括ContentLenght
和特殊Expect: 100-continue
标头)发送到服务器但没有正文。如果请求可接受,则等待服务器以状态码100响应。之后它开始发送身体。
其他信息:
MSDN Page for ServicePointManager.Expect100Continue
MSDN blog post with some details
在我的情况下,问题是协议的这一部分并没有得到后端服务(Play框架)的特别好处理,当请求大小太大而无法处理时,我正在与之交谈。它没有返回任何错误。请求只是超时。所以禁用它
ServicePointManager.Expect100Continue = false;
在向主机发送任何请求之前,我已经解决了这个问题。至少现在它正在回归。
如果这没有帮助,那么我建议的最好的事情就是使用wireshark或类似的东西来查看电线上发生的事情。如果你使用这个笨拙的工具很好玩。 (顺便说一句,感谢你的链接。我自己也在寻找这样的东西)