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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 09:42:26  来源:igfitidea点击:

Keep Alive not working properly on iOS

iosswiftxcodealamofirensurlsession

提问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日志:

  1. At 23.101902 the app makes an HTTP/1.1 POST request to the server with “Connection: keep-alive” enter image description here

  2. At 23.139422 the server responds HTTP/1.1 200 OK with “Connection: Keep-Alive” and “timeout=300” (300 seconds) enter image description here

  3. The Round-Trip-Time (RTT) is reported as 333.82 msec (this highlights the margin of error we have on the following timestamps):

  1. 在 23.101902,应用程序向服务器发出 HTTP/1.1 POST 请求,并带有“Connection: keep-alive” 在此处输入图片说明

  2. 在 23.139422,服务器以“Connection: Keep-Alive”和“timeout=300”(300 秒)响应 HTTP/1.1 200 OK 在此处输入图片说明

  3. 往返时间 (RTT) 报告为 333.82 毫秒(这突出了我们对以下时间戳的误差幅度):

enter image description here

在此处输入图片说明

  1. 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): enter image description here

  2. The test is repeated numerous times with an approx. time of 30 seconds being always monitored

  1. 但是,该应用程序会在 30 秒内关闭连接(大约考虑到 Internet 传输的变化——54.200863 和 23.451979 时间戳之间的差异): 在此处输入图片说明

  2. 该测试重复多次,大约为 始终监控 30 秒的时间

Test 2 logs on the server side:

服务端测试2日志:

  1. The HTTP/1.1 POST request from the app: enter image description here
  2. The HTTP OK server response with keep-alive being accepted and set at 300 seconds: enter image description here
  3. The RTT is at 859.849 msec enter image description here
  1. 来自应用程序的 HTTP/1.1 POST 请求: 在此处输入图片说明
  2. 接受保持活动状态的 HTTP OK 服务器响应并设置为 300 秒: 在此处输入图片说明
  3. RTT 为 859.849 毫秒 在此处输入图片说明

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 NSURLSessionclass defaults to ignoring the keep-aliveheader, 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 HTTPShouldUsePipeliningin 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 决定对无线电进行电源管理的积极程度,但至少您会祈祷。:-)