多次上传文件失去连接('The network conn
1.引子
近期项目开发过程中,有个需求是文件断点续传,同时上传数量为5。按照正常上传方法,采用NSOperationQueue作为任务队列,NSOperation作为任务,添加到NSOperationQueue,具体实现后面再写。说说其中发生的奇怪的问题,当一个操作在多次点击暂停上传后,开始上传,终端出现
Nw_connection_write_close 25 connection is not ready,sending error callback
__tcp_connection_write_eof_block_invoke write close callback receive error:[57] socket is not connected
结果就是不管怎样,重新启动,切换网络环境都不起任何作用,上传一直处于失败状态,即使重新从头开始上传,上传到那一段还是会失败。且报的错是<strong>“Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." "</strong>,但其实网络是相通的,接口调用都没有问题。
2.原因分析
经过Google,StackOverFlow,baidu后,查阅关键字
Nw_connection_write_close 25 connection is not ready,sending error callback
第一次试了修改"<strong>Accept-Encoding:deflate</strong>",然后在同样测试环境下进行测试,结果和之前一样,未能够修复;第二个方法是让服务器修改"<strong>Keep-Alive:timeout=5, max=100</strong>",或者更多,由于服务器是另外一个项目,没有权限进行尝试,况且别的项目没有说过这种情况,所以这种方法就不得而知,是否行得通;第三种方法也是我的解决方案,其中有这样一段话:
<strong>For this to work you must make sure that you use the right HTTP method for each request. There are two ways this can go wrong</strong>:
- If you use a non-idempotent HTTP method for an idempotent request, NSURLSession will not retry the request even though it could safely do so. This isn’t a serious problem; you can just retry the request yourself.
- If you use an idempotent HTTP method for a non-idempotent request, that’s very bad. NSURLSession might retry the request even though doing so is unsafe. The only valid solution here is to change your request to use a different HTTP method, which may require server-side changes.
翻译:
<strong>为此,您必须确保为每个请求使用正确的HTTP方法。 有两种方法可能会出错:</strong>
- 如果您使用非幂等HTTP方法进行幂等请求,NSURLSession即使可以安全地执行此操作,也不会重试该请求。 这不是一个严重的问题; 您可以自己重试请求。
- 如果对非幂等请求使用了幂等的HTTP方法,这是非常糟糕的。 NSURLSession可能会重试该请求,即使这样做是不安全的。 唯一有效的解决方案是更改您的请求以使用不同的HTTP方法,这可能需要服务器端更改。
到了现在我才知道HTTP有个幂等性,查阅资料
- 一个HTTP方法是幂等的,指的是同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。在正确实现的条件下,GET,HEAD,PUT和DELETE 等方法都是幂等的,而 POST 方法不是。所有的 safe 方法也都是幂等的。
- 幂等性只与后端服务器的实际状态有关,而每一次请求接收到的状态码不一定相同。例如,第一次调用DELETE 方法有可能返回 200,但是后续的请求可能会返回404。DELETE 的言外之意是,开发者不应该使用DELETE方法实现具有删除最后条目功能的 RESTful API。
我上传使用的请求是POST,属于非幂等性,上传中多次点击后再次上传会导致错误的更新。于是我改成幂等性且与POST请求功能一致的PUT请求,PUT是幂等性方法。经过多次实践测试后,没有出现<strong>失去连接("The Connect was Lost")</strong>的提示,并且之前上传失败的连接在修改为PUT请求后也能够继续上传。问题得到解决。
3.后续
经过这次Bug学习,了解到HTTP幂等性与非幂等性特性。也学习了POST、PUT请求的区别,对于这种有多次交互的请求的方法可以采用PUT请求试试哦!