降低请求带宽
降低带宽消耗的几种方式:
压缩响应
压缩响应是一种简单的优化带宽的方法,只需要服务器很小的改变即可。
response由headers和body组成。压缩响应是指利用算法将body压缩,而保留headers完好无损。JSON和XML格式的数据,可以被压缩到小于10%,压缩比例根据负载不同而不同,负载越大,压缩比就越大。
iOS全部的HTTP NSURLConnection 请求都默认可以压缩,给
NSURLConnection请求添加如下HTTP header:
Accept-Encoding: gzip, deflate
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:NSURLCacheStorageAllowed
timeoutInterval:20] autorelease];
[request addValue:@"" forHTTPHeaderField:@"Accept-Encoding"];
压缩响应需要设置服务器,压缩响应负载。首先添加两个模块:
LoadModule filter_module library-path/mod_filter.so
LoadModule deflate_module library-path/mod_deflate.so
然后设置要压缩的内容,最简单的,设置全部数据利用DEFLATE压缩:
SetOutputFilter DEFLATE
这种方式并不常用,因为它只对数据全部是text时,比较有效,如果数据时音频、图片等预压缩过的资源,占用CPU进行压缩,可是压缩后的资源size并不会有明显变小,划不来。一种更有效的方式是设置只压缩指定的、压缩后会明显减小size 的资源类型的资源,如下是压缩一些常见资源类型的代码:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/json
压缩请求
压缩请求非常必要,因为广域无线传输速度通常是不对称的,从服务器发送至设备带宽大,而将数据从设备发送出去带宽小。这主要是因为大多数的网络流量通常是不对称的。如果应用程序不是这种标准的非对称模式,就应该认真考虑压缩请求。
不同于压缩响应,压缩请求复杂很多,需要客户端和服务器端共同实现。
首先,需要为服务器设置一个input filter,用于响应压缩的相同模块在Apache中同时执行请求压缩。下面的配置片段加载所需的模块。
LoadModule filter_module library-path/mod_filter.so
LoadModule deflate_module library-path/mod_deflate.so
下一个步是定义一个input filter的DEFLATE模块。下面的代码片段定义了一个input filter和一个CGI别名:
SetInputFilter DEFLATE
SetOutputFilter DEFLATE
ScriptAlias /cgi/
- (NSData *)compressNSData:(NSData *)myData {
NSMutableData *compressedData = [NSMutableData dataWithLength:16384];
z_stream compressionStream;
compressionStream.next_in=(Bytef *)[myData bytes];
compressionStream.avail_in = [myData length];
compressionStream.zalloc = Z_NULL;
compressionStream.zfree = Z_NULL;
compressionStream.opaque = Z_NULL;
compressionStream.total_out = 0;
if (deflateInit2(&compressionStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) {
errorOccurred = YES;
return nil;
}
do {
if (compressionStream.total_out >= [compressedData length]) {
[compressedData increaseLengthBy:16386];
}
compressionStream.next_out = [compressedData mutableBytes] + compressionStream.total_out;
compressionStream.avail_out = [compressedData length] - compressionStream.total_out;
deflate(&compressionStream, Z_FINISH);
} while (compressionStream.avail_out == 0);
deflateEnd(&compressionStream);
[compressedData setLength: compressionStream.total_out];
return compressedData;
}
添加header代码如下,没有这个header,服务器模块不知道这个请求是压缩的。
[request addValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
NSData *compressed = [self compressNSData:myData];
[request setHTTPBody:compressed];
reqSize = [compressed length];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:[NSURL URLWithString:url]];
[request setHTTPShouldUsePipelining:YES];