保持活跃在iOS上无法正常工作

zir*_*isp 6 xcode ios nsurlsession swift alamofire

我目前正在开发一个应用程序,我们需要一些请求才能尽快访问我们的服务器。为了加快请求过程,我们必须消除握手(这需要花费额外的时间)并建立永久连接。

该应用程序使用Alamofire框架向我们的服务器发出所有请求,并且设置如下:

我们有一个使用默认配置和http标头设置的会话管理器。

lazy var sessionManager: Alamofire.SessionManager = {
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let manager = Alamofire.SessionManager(configuration: configuration)
    return manager
}()
Run Code Online (Sandbox Code Playgroud)

会话管理器对所有请求都是持久的。每个请求使用以下代码进行:

self.sessionManager.request(request.urlString, method: request.method, parameters: request.parameters)
            .responseJSON { [weak self] response in
    // Handle the response
}
Run Code Online (Sandbox Code Playgroud)

request.urlString是我们服务器的网址“ http://ourserver.com/example

request.method设置为post

request.parameters是参数字典

该请求运行正常,我们收到了有效的回复。该问题出现在存活计时器上,该计时器由我们的服务器设置为300秒。该设备在wifi上最多可保持30秒的连接,并通过GSM几乎立即将其关闭。


服务器调试

我们在服务器上进行了一些调试,发现以下结果

测试:

测试1:

  • iPhone通过WiFi连接到Internet

测试2:

  • iPhone通过3G连接到Internet

行为:

  • 两种情况:应用程序使用“连接:保持活动”向Web服务器发出HTTP / 1.1请求;服务器(服务器ip = 10.217.81.131)响应为“保持活动:超时= 300,最大值= 99”
  • 客户端(测试1-WiFi上的应用程序)在30秒发送TCP FIN并关闭连接
  • 客户端(测试2 – 3G上的应用程序)从其第一个HTTP POST收到HTTP / 1.1 OK消息后立即发送(零秒)TCP FIN请求

测试1在服务器端登录:

  1. 在23.101902,应用程序通过“连接:保持活动”向服务器发出HTTP / 1.1 POST请求 在此处输入图片说明

  2. 在23.139422,服务器通过“连接:保持活动”和“超时= 300”(300秒)响应HTTP / 1.1 200 OK。 在此处输入图片说明

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

在此处输入图片说明

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

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

测试2在服务器端登录:

  1. 来自应用程序的HTTP / 1.1 POST请求: 在此处输入图片说明
  2. 接受保持活动状态的HTTP OK服务器响应,并将其设置为300秒: 在此处输入图片说明
  3. RTT为859.849毫秒 在此处输入图片说明

应用程序立即关闭连接,立即为21.197918 – 18.747780 = 2.450138秒

从WiFi切换到3G并返回时,重复测试,并记录相同的结果。

客户端调试

使用WiFi

首次尝试(建立连接)

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])
Run Code Online (Sandbox Code Playgroud)

第二次尝试(在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])
Run Code Online (Sandbox Code Playgroud)

然后30秒后,连接断开(FI)

使用3G

第一次尝试

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])
Run Code Online (Sandbox Code Playgroud)

然后,连接几乎立即断开。

dga*_*ood 5

现在我又看了一遍代码,我想我看到了问题所在。底层NSURLSession类默认忽略keep-alive标头,因为某些服务器“支持”它,但实际上,如果您实际尝试使用它,IIRC 会严重破坏。

如果您希望会话支持保持活动状态,则必须HTTPShouldUsePipelining在会话配置中明确设置为YES.

请注意,仍然无法保证连接会保持正常,这取决于 iOS 决定对无线电进行电源管理的积极程度,但至少您会祈祷。:-)

  • 我们尝试将 HTTPShouldUsePipelining 设置为 true,我们得到了相同的结果。 (2认同)