xcode Keep Alive 在 iOS 上无法正常工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41482187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Keep Alive not working properly on iOS
提问by zirinisp
I am currently developing an application where we need some request to hit our server ASAP. To speed up the request process we have to eliminate handshake (as it takes extra) and have a permanent connection.
我目前正在开发一个应用程序,我们需要一些请求来尽快访问我们的服务器。为了加快请求过程,我们必须消除握手(因为它需要额外的费用)并拥有永久连接。
The application is using the Alamofire framework to make all request to our server and the setup is the following:
该应用程序使用 Alamofire 框架向我们的服务器发出所有请求,设置如下:
We have a session manager set up with default configuration and http header.
我们有一个使用默认配置和 http 标头设置的会话管理器。
lazy var sessionManager: Alamofire.SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
let manager = Alamofire.SessionManager(configuration: configuration)
return manager
}()
The session manager is persistent across all requests. Each request is made using the following code:
会话管理器在所有请求中都是持久的。每个请求都是使用以下代码发出的:
self.sessionManager.request(request.urlString, method: request.method, parameters: request.parameters)
.responseJSON { [weak self] response in
// Handle the response
}
request.urlString is the url of our server "http://ourserver.com/example"
request.urlString 是我们服务器的 url " http://ourserver.com/example"
request.method is set to post
request.method 设置为 post
request.parameters is a dictionary of paramaters
request.parameters 是一个参数字典
The request is working fine and we get a valid response. The problem arises on the keep alive timer, which is set by our server to 300 seconds. The device holds the connection for a maximum of 30 seconds on wifi and closes it almost instantly over GSM.
请求工作正常,我们得到了有效的响应。问题出现在保持活动计时器上,我们的服务器将其设置为 300 秒。该设备在 wifi 上保持连接最多 30 秒,并通过 GSM 几乎立即关闭它。
Server Debug
服务器调试
We did some debugging on our server and found the following results
我们在我们的服务器上做了一些调试,发现了以下结果
Tests:
测试:
Test 1:
测试 1:
- iPhone connects to the Internet via WiFi
- iPhone 通过 WiFi 连接到互联网
Test 2:
测试 2:
- iPhone connects to the Internet via 3G
- iPhone 通过 3G 连接到互联网
Behaviour:
行为:
- Both cases: app makes an HTTP/1.1 request to a web server with “Connection: keep-alive”; The Server (server ip = 10.217.81.131) responds with “Keep-Alive: timeout=300, max=99”
- The client side (test 1 - app over WiFi) sends TCP FIN on the 30th second and the connection closes
- The client side (test 2 – app over 3G) sends immediately (zero seconds) a TCP FIN request after it receives the HTTP/1.1 OK message from its first HTTP POST
- 两种情况:应用程序向 Web 服务器发出 HTTP/1.1 请求并带有“Connection: keep-alive”;服务器(服务器 ip = 10.217.81.131)响应“Keep-Alive: timeout=300, max=99”
- 客户端(test 1 - app over WiFi)在第 30 秒发送 TCP FIN,连接关闭
- 客户端(测试 2 – 3G 上的应用程序)在收到来自其第一个 HTTP POST 的 HTTP/1.1 OK 消息后立即(零秒)发送 TCP FIN 请求
Test 1 logs on the server side:
服务端测试1日志:
At 23.101902 the app makes an HTTP/1.1 POST request to the server with “Connection: keep-alive”
At 23.139422 the server responds HTTP/1.1 200 OK with “Connection: Keep-Alive” and “timeout=300” (300 seconds)
The Round-Trip-Time (RTT) is reported as 333.82 msec (this highlights the margin of error we have on the following timestamps):
在 23.101902,应用程序向服务器发出 HTTP/1.1 POST 请求,并带有“Connection: keep-alive”
在 23.139422,服务器以“Connection: Keep-Alive”和“timeout=300”(300 秒)响应 HTTP/1.1 200 OK
往返时间 (RTT) 报告为 333.82 毫秒(这突出了我们对以下时间戳的误差幅度):
The app, however, closes the connection in 30 seconds (approx. given the Internet transport variations – the difference between the 54.200863 and the 23.451979 timestamps):
The test is repeated numerous times with an approx. time of 30 seconds being always monitored
但是,该应用程序会在 30 秒内关闭连接(大约考虑到 Internet 传输的变化——54.200863 和 23.451979 时间戳之间的差异):
该测试重复多次,大约为 始终监控 30 秒的时间
Test 2 logs on the server side:
服务端测试2日志:
- The HTTP/1.1 POST request from the app:
- The HTTP OK server response with keep-alive being accepted and set at 300 seconds:
- The RTT is at 859.849 msec
The app closes immediately the connection, where immediately is 21.197918 – 18.747780 = 2.450138 seconds
该应用程序立即关闭连接,其中立即为 21.197918 – 18.747780 = 2.450138 秒
The tests are repeated while switching from WiFi to 3G and back with the same results being recorded.
在从 WiFi 切换到 3G 并返回时重复测试,并记录相同的结果。
Client Debug
客户端调试
Using WiFi
使用无线网络
First Attempt (connection established)
第一次尝试(建立连接)
Optional(
[AnyHashable("Content-Type"): text/html,
AnyHashable("Content-Encoding"): gzip,
AnyHashable("Content-Length"): 36,
AnyHashable("Set-Cookie"): user_cookieuser_session=HXQuslXgivCRKd%2BJ6bkg5D%2B0pWhCAWkUPedUEGyZQ8%2Fl65UeFcsgebkF4tqZQYzVgp2gWgAQ3DwJA5dbXUCz4%2FnxIhUTVlTShIsUMeeK6Ej8YMlB11DAewHmkp%2Bd3Nr7hJFFQlld%2BD8Q2M46OMRGJ7joOzmvH3tXgQtRqR9gS2K1IpsdGupJ3DZ1AWBP5HwS41yqZraYsBtRrFnpGgK0CH9JrnsHhRmYpD40NmlZQ6DWtDt%2B8p6eg9jF0xE6k0Es4Q%2FNiAx9S9PkhII7CKPuBYfFi1Ijd7ILaCH5TXV3vipz0TmlADktC1OARPTYSwygN2r6bEsX15Un5WUhc2caCeuXnmd6xy8sbjVUDn72KELWzdmDTl6p5fRapHzFEfGEEg2LOEuwybmf2Nt6DHB6o6EA5vfJovh2obpp4HkIeAQ%3D; expires=Sun, 08-Jan-2017 12:51:43 GMT; path=/,
AnyHashable("Keep-Alive"): timeout=300, max=100,
AnyHashable("Connection"): Keep-Alive,
AnyHashable("X-Powered-By"): PHP/5.3.10-1ubuntu3.11,
AnyHashable("Server"): Apache/2.2.22 (Ubuntu),
AnyHashable("Vary"): Accept-Encoding,
AnyHashable("Date"): Sun, 08 Jan 2017 10:51:43 GMT])
Second Attempt (within 30 sec, the connection is still alive)
第二次尝试(30 秒内,连接仍然有效)
Optional([AnyHashable("Content-Type"): text/html,
AnyHashable("Content-Encoding"): gzip,
AnyHashable("Content-Length"): 36,
AnyHashable("Keep-Alive"): timeout=300, max=99,
AnyHashable("Connection"): Keep-Alive,
AnyHashable("X-Powered-By"): PHP/5.3.10-1ubuntu3.11,
AnyHashable("Server"): Apache/2.2.22 (Ubuntu),
AnyHashable("Vary"): Accept-Encoding,
AnyHashable("Date"): Sun, 08 Jan 2017 11:00:18 GMT])
Then after 30 seconds the connection drops (FI)
然后在 30 秒后连接断开 (FI)
Using 3G
使用 3G
First Attempt
第一次尝试
Optional([AnyHashable("Content-Type"): text/html,
AnyHashable("Content-Encoding"): gzip,
AnyHashable("Content-Length"): 36,
AnyHashable("Connection"): keep-alive,
AnyHashable("X-Powered-By"): PHP/5.3.10-1ubuntu3.11,
AnyHashable("Server"): Apache/2.2.22 (Ubuntu),
AnyHashable("Vary"): Accept-Encoding,
AnyHashable("Date"): Sun, 08 Jan 2017 11:04:31 GMT])
Then the connection drops almost instantly.
然后连接几乎立即断开。
回答by dgatwood
Now that I looked at the code a second time, I think I see the problem. The underlying NSURLSession
class defaults to ignoring the keep-alive
header, because some servers "support" it, but in practice, break badly if you actually try to use it, IIRC.
现在我又看了一遍代码,我想我看到了问题所在。底层NSURLSession
类默认忽略keep-alive
标头,因为某些服务器“支持”它,但在实践中,如果您实际尝试使用它,IIRC 会严重破坏。
If you want a session to support keep-alive, you have to explicitly set HTTPShouldUsePipelining
in the session configuration to YES
.
如果您希望会话支持保持活动状态,则必须HTTPShouldUsePipelining
在会话配置中明确设置为YES
.
Note that there is still no guarantee that the connection will stay up, depending on how aggressively iOS decides to power manage the radio, but at least you'll have a prayer. :-)
请注意,仍然无法保证连接会保持正常,这取决于 iOS 决定对无线电进行电源管理的积极程度,但至少您会祈祷。:-)