Skip to content

Commit 80068a8

Browse files
committed
🚀 Add implementation of downstream traffic
1 parent e62bf00 commit 80068a8

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,63 @@ int HTTPMessage::copySerializedMessage()() {
17861786
}
17871787
```
17881788

1789+
#### 下行流量
1790+
1791+
下行流量的思路也类似,主要计算每个响应报文的大小,包含报文首部和报文主体,两者之间有个空行,报文首部包含状态行和首部字段。实现上会用到 `NSHTTPURLResponse``allHeaderFields``expectedContentLength` 属性。但这里需要注意的是 `expectedContentLength` 属性可能会为 `NSURLResponseUnknownLength`(-1),主要是在有些请求的响应的首部字段中没有 `Content-Length` 字段,或者没有告知具体响应大小时出现。那么这个时候需要通过其他的机制去计算。
1792+
1793+
```
1794+
- (int64_t)p_getResponseLength {
1795+
int64_t responseLength = 0;
1796+
if (_response && [_response isKindOfClass:[NSHTTPURLResponse class]]) {
1797+
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)_response;
1798+
NSDictionary<NSString *, NSString *> *headerFields = httpResponse.allHeaderFields;
1799+
NSUInteger headersLength = [self p_getHeadersLength:headerFields];
1800+
int64_t contentLength = (httpResponse.expectedContentLength != NSURLResponseUnknownLength) ?
1801+
httpResponse.expectedContentLength :
1802+
_dataLength;
1803+
responseLength = headersLength + contentLength;
1804+
}
1805+
return responseLength;
1806+
}
1807+
```
1808+
1809+
在上面代码中会去判断 `expectedContentLength` 是否为 `NSURLResponseUnknownLength`,如果不是响应报文主体的大小就是 `expectedContentLength`,否则将其赋值为 `_dataLength``_dataLength` 的计算可以在响应的回调中去计算,比如下面代码罗列的这几个地方。
1810+
1811+
```
1812+
- (void)wtn_URLSession:(NSURLSession *)session
1813+
dataTask:(NSURLSessionDataTask *)dataTask
1814+
didReceiveData:(NSData *)data {
1815+
WTNHTTPTransactionMetrics *httpTransaction = dataTask.httpTransaction;
1816+
httpTransaction.dataLength += data.length;
1817+
1818+
if ([self.originalDelegate respondsToSelector:@selector(URLSession:dataTask:didReceiveData:)]) {
1819+
[(id)self.originalDelegate URLSession:session dataTask:dataTask didReceiveData:data];
1820+
}
1821+
}
1822+
1823+
1824+
- (NSURLSessionDataTask *)wtn_dataTaskWithRequest:(NSURLRequest *)request
1825+
completionHandler:(void (^)(NSData * _Nullable data,
1826+
NSURLResponse * _Nullable response,
1827+
NSError * _Nullable error))completionHandler {
1828+
WTNHTTPTransactionMetrics *httpTransaction = [WTNHTTPTransactionMetrics new];
1829+
1830+
······
1831+
1832+
if (completionHandler) {
1833+
wrappedCompletionHandler = ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
1834+
httpTransaction.dataLength = data.length;
1835+
};
1836+
}
1837+
1838+
······
1839+
1840+
return dataTask;
1841+
}
1842+
```
1843+
1844+
`wtn_URLSession:dataTask:didReceiveData` 是 hook 之后的回调函数,因为在大文件中这个回调会执行多次,所以这里使用 `+=``wtn_dataTaskWithRequest:completionHandler:` 也是 hook 函数,类似的还有 `wtn_uploadTaskWithRequest:fromData:completionHandler:``wtn_uploadTaskWithRequest:fromFile:completionHandler` 等。
1845+
17891846
## Power consumption
17901847

17911848
iOS 设备的电量一直是用户非常关心的问题。如果你的应用由于某些缺陷不幸成为电量杀手,用户会毫不犹豫的卸载你的应用,所以耗电也是 App 性能的重要衡量标准之一。然而事实上业内对耗电量的监控的方案都做的不太好,下面会介绍和对比业内已有的耗电量的监控方案。

0 commit comments

Comments
 (0)